namespace (for export)

Jonathan M Davis jmdavisProg at gmx.com
Thu Nov 25 15:42:33 PST 2010


On Thursday 25 November 2010 09:55:44 spir wrote:
> On Thu, 25 Nov 2010 03:03:24 -0800
> 
> Jonathan M Davis <jmdavisProg at gmx.com> wrote:
> > I really don't get what you're trying to do, since previous posts on this
> > topic
> 
> that you've made indicate that you're trying to put statements at the
> module level, which makes no sense at all. All statements must be in a
> function and thus have an execution path.
> 
> In the general case, defining symbols requires kinds of statement (but I
> don't see what you mean by "statement" as for me an assignemnt is the
> archetype of a statement, so how can you define anything?). Anyway, if I
> put definitions in a func, as you propose, then how can I have the symbols
> available for export? The answer seems to be: declare them first as
> globals. Right, but then we get this double definition issue (not that
> serious, just annoying); it's just a useless hack. What I don't understand
> is why the language refuses the same exact definition at the toplevel that
> it accepts in a func. You seems to take it for granted that I cannot
> write:
> 	auto myExportedSymbol = new T();
> 	...
> 	myExportedSymbol.i = 1;
> but for me there is no obvious reason why D refuses that, and accepts
> 	T myExportedSymbol;
> 	static this () {
> 	   auto myExportedSymbol = new T();
> 	   ...
> 	   myExportedSymbol.i = 1;
> 	}
> It's the same thing, from my point of view: when I import the module, I get
> the symbol correctly defined. I don't get why a module needs a
> constructor: why else has it a top-level?
> 
> > All a module constructor is for is initializing global variables at
> > runtime.
> 
> Precising runtime to import time, that's exactly what I'm looking for. How
> can one do it without static this?

1. All declarations other than non-static locals are done at compile time. 
Conceptually, they can run in any order. Unlike in a function, there is no 
execution path for them to be run on. So, if you have

int i = 7;
float g = 2.1;

there's nothing that says that i must be initialized before g. Such declarations 
are purely declarative in nature such as you'd expect from declarative 
programming.

2. static this blocks - be they module constructors or static class or static 
struct constructors - are essentially special functions which are run in lexical 
order in each module prior to main (and prior to the unittest blocks if -
unittest is used). They're completely at runtime and provide an execution path 
statements so that you can initialize globals and static class/struct variables 
with stuff that can only be done at runtime or uses other globals or statics as 
part of the initialization. Modules which circularly import each other cannot 
have module constructors precisely because that creates problems with knowing 
the proper order to run the module constructors to avoid interdependencies and 
thus avoid trying to use a variable before it has actually been initialized.

3. imports import the symbols table. The code may or may not have been fully 
compiled before an import is processed. If modules are interdependent, then it 
can't have been. importing a module also cannot affect the module being imported, 
or the order of imports and the order of the compilation of modules matters, and 
whether you import a particular module could affect other modules. Modules are 
independent, can be compiled in any order - barring interdependencies - and are 
only compiled once. So, having a module affected by a module importing it does 
not work at all. And because symbols can at least be partially - if not fully - 
compiled independently, having a global variable affected by whether it was 
imported or not doesn't work at all - especially when it could be a third party 
which imports it. If your module were in a compiled library (be it shared or 
static), and someone using that library imports it, your code has already been 
compiled and all compile-time initialization done, so it there's no way that you 
could have modules be affected by who imports them or even know whether any 
modules actually do import them.

It is true that some languages do not make symbols as independent of each other 
as D does - C and C++ are particularly bad with how #include works - and for a 
number of languages, global variables are initialized at runtime in 
lexigraphical order (C++ and Java both do that), but that creates 
interdependencies and bugs which only pop up at runtime when variables were 
declared in a particular order. It's very messy, although if you're careful or 
don't do much with globals or static variables, it's not generally a problem. D 
doesn't do things that way. It made it so that all global and static variables 
must be initialized at compile-time (avoiding all of the ordering and 
interdependcy problems except for those posed by module constructors). This not 
only avoids bugs, but it makes it possible for the compiler to parallelize their 
compilation on a _much_ greater level than would be possible in a language like 
C++ or Java. And while, languages like C++ and Java do do global initializations 
at runtime and in do it lexographical order, they're still conceptually doing 
declarative programming, so it really doesn't make sense for them to put 
statements directly in the module either (though in their case, the 
implementation doesn't quite match the concept). Java added static constructors 
to help fix the problem, and D took it a step further by making global 
initializations have to be done at compile time or in a static constructor.

So, what you're trying to do just doesn't work with D's compilation model, or 
really the compilation model of any C-based language, I don't believe. In D, 
modules are essentially independent, and all compilation is made as independent 
as possible. Obviously, there is a dependence on order in functions (be they 
static constructors or normal functions), but that's pretty much the only place 
that order matters. So, I really don't think that you're going to be able to do 
what you're trying to do like you've been trying to do it.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list