The ever evolving DWScript project continues to advance the Pascal language at an impressive pace. Just today it was announced that this scripting version of Pascal now has “namespace” support.
When I first read the details of the implementation, my initial reaction was that it “felt a bit backwards”. The essence of the implementation is that it involves a new syntax for a unit, which instead of representing an actual unit, creates a “virtual” unit that effectively acts to collate or aggregate a number of other units into a single name:
unit namespace Foo.Bar; uses Foo.Bar.One, Foo.Bar.Two;
Then in some other unit you can use both Foo.Bar.One and Foo.Bar.Two by simply using the namespace that is thus declared as using it:
unit MyUnit; uses Foo.Bar; // uses Foo.Bar.One and Foo.Bar.Two
As I say, whilst useful and powerful, it feels a bit backwards to me.
That is, you have to declare a namespace and then say what is in it, when it seems more natural to me for a unit to say which namespace it is a part of, itself. Apart from anything else, it seems to me that using this “this namespace consists of” approach (vs “I am part of a namespace“) you can end up with two units in two different namespaces, no ?
unit namespace Foo.Bar; uses Foo.Bar.One, Foo.Bar.Two;
unit namespace Snafu; uses Snafu.One, Foo.Bar.One;
Having said that, whilst this might make me a little uncomfortable, is it actually a problem as such ? If a unit then uses both Foo.Bar and Snafu namespaces, presumably the aggregated unit lists that comprise those namespaces will be reduced to a list of unique units.
So perhaps not a problem at all.
In fact, it could be seen as a feature, since it would – presumably – allow you to have a namespace that brings an entire other namespace with it. i.e. Snafu might itself bring in the entire Foo.Bar namespace, so that if your unit then uses Snafu, it is automatically using not just Snafu itself but also the entire Foo.Bar namespace, without having to declare this separately.
Convenient, certainly, but what is an irritant when creating code (having to declare used units) can often be a boon when it comes to maintenance (being able to see at a glance what units are used by any given unit).
I should add at this point that this post is not intended to critique or suggest an alternative approach for DWScript itself. Rather it is inspired by thinking about how such a feature would work in an actual, compiled Pascal project – specifically Delphi.
So, DWScript has it’s new namespace declaration unit, but I think even that can be made a bit more Delphi-like if it were to be adopted by Delphi itself.
Delphi already has a module type which acts as – and thus has an appropriate syntax for – a container for other units. The package.
We need to change the module keyword, but that’s OK and indeed desirable, since we are now defining an entirely new module type, giving us a great deal more flexibility in devising an appropriate syntax for that module. But we needn’t work too hard, since a lot of the existing package syntax “just fits”:
namespace Foo.Bar; contains Foo.Bar.One in '..\Foo\Foo.Bar.One.Pas', Foo.Bar.Two in '..\Foo\Foo.Bar.Two.Pas'; end.
This syntax allows us to better reflect the “containment” relationship that a namespace has with it’s members, as opposed to the “uses” declaration. But this still has us declaring a namespace and then identifying it’s contents. It still “feels backwards”.
It makes more sense – to me anyway – for a unit to declare it’s namespace and, continuing the theme of recycling existing syntax where it fits, there is just such a syntax that works in this case. I deliberately invoked that syntax in my “namespace” module example above:
The in clause.
We could simply [ ] add support for that to the module declaration in a unit:
unit Foo.Bar.One in Foo.Bar;
This seems very neat and elegant to me but it has one major problem. As Andreas Hausladen mentioned in the comments on the DWScript post: the one-pass compiler in Delphi.
When the compiler finds a unit that “uses Foo.Bar” it doesn’t know that Foo.Bar is a namespace or which units are contained within that namespace. It won’t find out that Foo.Bar.One even exists or that it is part of Foo.Bar unless and until it is asked to reference Foo.Bar.One itself, which sort of defeats the purpose of namespaces, right out of the gate.
If this could be solved as elegantly as the syntax for declaring the membership of a namespace itself (using this in syntax) then I think we’d have a winner.
One way perhaps of resolving the, uh, resolving problem might be to introduce an initial first-pass in the compilation of a Delphi project, specifically to resolve namespaces. This pass would use the existing uses declarations in the dpr combined with the project (and environment) search path (i.e. the current “unit search” algorithm) to assemble a directory of units and their corresponding namespace ‘containers’, where applicable.
The bulk of this work – the business of locating a given unit on the search path – is already done by the compiler. But with a directory of unit locations produced by the first pass, the compiler would be relieved of this effort. Consequently the “cost” of the first pass would be offset – at least in part – by the removal of this effort from the compiler itself.
It is also worth mentioning that even the “namespace module” would introduce some problems to be solved in any Delphi compiler implementation, since any namespace implementation creates the possibility, and increases the likelihood, of duplicate references to units in a single uses clause:
uses Foo.Bar, // uses Foo.Bar.One and Foo.Bar.Two Snafu; // uses Snafu.One and Foo.Bar.One
Currently, if a unit is referenced more than once in a uses clause (or indeed is referenced in both interface and implementation uses clauses) then a compilation error results. Either this would have to be relaxed to a warning or ignored entirely, if namespaces are to be implemented.
This is perhaps less of a potential problem when a unit is confined to a single namespace, as would be the case if namespace membership were a declared aspect of a unit itself. But still a potential problem.
The Undiscovered Country
Luckily, whilst we might speculate and invent a future namespace feature for Delphi, it doesn’t actually exist as yet (as far as I know). This means we get to decide how we might like that future to actually look, from among the various options.
So which would you prefer:
- A namespace module, declaring the units contained in the namespace
- An in declaration on a unit, with a name resolution pass added to the compiler
- Some other approach ?
Comments are now closed.