Thread overview
Proposal: "import thing;" checks for thing/thing.d before it tries thing.d
Nov 28, 2005
Don Clugston
Nov 29, 2005
Bruno Medeiros
Nov 29, 2005
Georg Wrede
November 28, 2005
A recent post by Alan West contained an idea which I think is worthy of further consideration. I've probably distorted it beyond recognition, though :-)

EXISTING BEHAVIOUR

import outer.inner;

looks for the file "outer/inner.d", and henceforth outer.inner can only refer to that file.

But,

import outer.inner.thing;

looks for the file "outer/inner/thing.d" and henceforth, outer.inner can only refer to the directory.
If outer contains both inner/thing.d and inner.d, either of those above two lines will compile, but if both are used, compilation will fail. This behaviour is undesirable. When used together, either both should work, or both should fail.

However, if something like this worked, there would be some appealing consequences, as discussed below.

PROPOSAL  - Somewhat analagous to implicit template properties.

It is an error to refer to "outer.inner" in any form, if both outer/inner.d and outer/inner/ exist.

import outer.inner;

would be resolved as follows.
Does outer/inner exist?
CASE A: YES -> ASSERT(outer.inner.d does not exist)
       The required module is "outer/inner/inner.d".
CASE B: NO -> The required module is "outer/inner.d"

More generally,
p.q.r.s
refers to either "p/q/r/s/s.d" or "p/q/r/s.d" depending on whether the last element exists as a directory, or not.

Internally, the compiler would use the fully qualified name, ("p/q/r/s/s"), but could collapse them ("p/q/r/s") when any kind of IO is required, eg error messages.

An often requested feature is the Java-style

import somepackage.*;

but this is unsafe, because the meaning of the program could change if another file were added to the somepackage directory, making it impossible for the author of 'somepackage' to safely extend the library.
With this proposal, the author could provide somepackage/somepackage.d
which would allow the exceedingly simple:

import somepackage;

Now you could follow Derek's suggestion and provide somepackage/all.d, but that has the consequence that later on, somepackage.all might not really be "all"! (it would just be "all" the version 1.0 files).

That's just syntactic sugar, and not very compelling. But more interesting to me, is that it would allow an existing file to be turned into a directory. There are two cases in Phobos where this would be very useful:

std/math.d

could be changed into std/math/math.d, std/math/statistic.d, std/math/discrete.d,...

and existing code that used

import std.math;

would continue to work correctly, yet we could also write
import std.math.statistic;
to import functions from mathematical statistics.

Another case where this would be useful is in
std.c.windows.windows

import std.c.windows;
would just import the windows.d header file, but
import std.c.windows.directx;
would import the DirectX headers. Subsequently, there might
be be optional parts of DirectX, so that could also become a directory,
with a directx.d file retained for backwards compatibility.

Since there are no header files in D, IMHO it's important to have mechanism for reducing file size. There is a problem in std.math.d; it is much too big. The problem has been concealed somewhat by moving most of the implementation into C functions; but that's not a general solution.

I believe that this situation is quite common, and arises whenever a module expands more than originally expected. This proposal would give a library maintainer considerable flexibility.
November 29, 2005
Don Clugston wrote:
> A recent post by Alan West contained an idea which I think is worthy of further consideration. I've probably distorted it beyond recognition, though :-)
> 
> EXISTING BEHAVIOUR
> 
> import outer.inner;
> 
> looks for the file "outer/inner.d", and henceforth outer.inner can only refer to that file.
> 
> But,
> 
> import outer.inner.thing;
> 
> looks for the file "outer/inner/thing.d" and henceforth, outer.inner can only refer to the directory.
> If outer contains both inner/thing.d and inner.d, either of those above two lines will compile, but if both are used, compilation will fail. This behaviour is undesirable. When used together, either both should work, or both should fail.
> 
> However, if something like this worked, there would be some appealing consequences, as discussed below.
> 
> PROPOSAL  - Somewhat analagous to implicit template properties.
> 
> It is an error to refer to "outer.inner" in any form, if both outer/inner.d and outer/inner/ exist.
> 
> import outer.inner;
> 
> would be resolved as follows.
> Does outer/inner exist?
> CASE A: YES -> ASSERT(outer.inner.d does not exist)
>        The required module is "outer/inner/inner.d".
> CASE B: NO -> The required module is "outer/inner.d"
> 
> More generally,
> p.q.r.s
> refers to either "p/q/r/s/s.d" or "p/q/r/s.d" depending on whether the last element exists as a directory, or not.
> 
> Internally, the compiler would use the fully qualified name, ("p/q/r/s/s"), but could collapse them ("p/q/r/s") when any kind of IO is required, eg error messages.
> 
> An often requested feature is the Java-style
> 
> import somepackage.*;
> 
> but this is unsafe, because the meaning of the program could change if another file were added to the somepackage directory, making it impossible for the author of 'somepackage' to safely extend the library.
> With this proposal, the author could provide somepackage/somepackage.d
> which would allow the exceedingly simple:
> 
> import somepackage;
> 
> Now you could follow Derek's suggestion and provide somepackage/all.d, but that has the consequence that later on, somepackage.all might not really be "all"! (it would just be "all" the version 1.0 files).
> 

Hum...

> That's just syntactic sugar, and not very compelling. But more interesting to me, is that it would allow an existing file to be turned into a directory. There are two cases in Phobos where this would be very useful:
> 
> std/math.d
> 
> could be changed into std/math/math.d, std/math/statistic.d, std/math/discrete.d,...
> 
> and existing code that used
> 
> import std.math;
> 
> would continue to work correctly, yet we could also write
> import std.math.statistic;
> to import functions from mathematical statistics.
> 

Another possible solution would be to simply allow a package to have te same name as a module. Wouldn't cause any language problems that I can see, but it would be a significant core change, as the structured module system would now be more akin to namespaces (the fundamental difference, for those who are not clear, is that a namespace-like module can contain other modules/namespaces). It would be, however, a weird namespace system, because of the module to file/directory correspondences.

Or another possible (also big-change) solution would be to adopt a conventional namespace system (like C++, C#).

I'm not actually sugesting this change, I'm just saying it. This bordelines one a more general issue I've brought up before, the D structured naming system (see http://www.digitalmars.com/d/archives/digitalmars/D/28423.html ) , and altough I *know* the current D status is ... well, _broken_ (or misguided, I can't find the right word), I'm not sure what would be the best way for this whole thing to work. (altough I'm clear on how certain aspects should be, some on them are mentioned on that thread)


-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
November 29, 2005
Don Clugston wrote:
> A recent post by Alan West contained an idea which I think is worthy
> of further consideration. I've probably distorted it beyond
> recognition, though :-)
> 
> EXISTING BEHAVIOUR
> 
> import outer.inner;
> 
> looks for the file "outer/inner.d", and henceforth outer.inner can
> only refer to that file.
> 
> But,
> 
> import outer.inner.thing;
> 
> looks for the file "outer/inner/thing.d" and henceforth, outer.inner
> can only refer to the directory. If outer contains both inner/thing.d
> and inner.d, either of those above two lines will compile, but if
> both are used, compilation will fail. This behaviour is undesirable.
> When used together, either both should work, or both should fail.
> 
> However, if something like this worked, there would be some appealing
>  consequences, as discussed below.
> 
> PROPOSAL  - Somewhat analagous to implicit template properties.
> 
> It is an error to refer to "outer.inner" in any form, if both outer/inner.d and outer/inner/ exist.
> 
> import outer.inner;
> 
> would be resolved as follows. Does outer/inner exist? CASE A: YES ->
> ASSERT(outer.inner.d does not exist) The required module is
> "outer/inner/inner.d". CASE B: NO -> The required module is
> "outer/inner.d"
> 
> More generally, p.q.r.s refers to either "p/q/r/s/s.d" or "p/q/r/s.d"
> depending on whether the last element exists as a directory, or not.
> 
> Internally, the compiler would use the fully qualified name, ("p/q/r/s/s"), but could collapse them ("p/q/r/s") when any kind of
> IO is required, eg error messages.
> 
> An often requested feature is the Java-style
> 
> import somepackage.*;
> 
> but this is unsafe, because the meaning of the program could change
> if another file were added to the somepackage directory, making it impossible for the author of 'somepackage' to safely extend the
> library. With this proposal, the author could provide
> somepackage/somepackage.d which would allow the exceedingly simple:
> 
> import somepackage;
> 
> Now you could follow Derek's suggestion and provide
> somepackage/all.d, but that has the consequence that later on,
> somepackage.all might not really be "all"! (it would just be "all"
> the version 1.0 files).
> 
> That's just syntactic sugar, and not very compelling. But more interesting to me, is that it would allow an existing file to be
> turned into a directory. There are two cases in Phobos where this
> would be very useful:
> 
> std/math.d
> 
> could be changed into std/math/math.d, std/math/statistic.d, std/math/discrete.d,...
> 
> and existing code that used
> 
> import std.math;
> 
> would continue to work correctly, yet we could also write import
> std.math.statistic; to import functions from mathematical statistics.

Now, this is the first Deep thing about imports I've seen. Once one understands this proposal, it gets very hard to accept the other proposed alternatives.

> Another case where this would be useful is in std.c.windows.windows
> 
> import std.c.windows; would just import the windows.d header file,
> but import std.c.windows.directx; would import the DirectX headers.
> Subsequently, there might be be optional parts of DirectX, so that
> could also become a directory, with a directx.d file retained for
> backwards compatibility.
> 
> Since there are no header files in D, IMHO it's important to have mechanism for reducing file size. There is a problem in std.math.d;
> it is much too big. The problem has been concealed somewhat by moving
> most of the implementation into C functions; but that's not a general
> solution.
> 
> I believe that this situation is quite common, and arises whenever a
>  module expands more than originally expected. This proposal would
> give a library maintainer considerable flexibility.