DIP16: Transparently substitute module with package

Michel Fortin michel.fortin at michelf.com
Thu Apr 5 16:32:15 PDT 2012


On 2012-04-05 21:43:24 +0000, Andrei Alexandrescu 
<SeeWebsiteForEmail at erdani.org> said:

> I think we should be looking for a solution that not only allows 
> replacing module -> package transparently, but also allows people to 
> import the newly introduced fine-grained modules.

I think it'd be valuable too. But how do you do that without creating 
ambiguous fully qualified names?

One way would be that by importing a module inside a package, the 
compiler would check first that the package file contains no symbol 
with that module name. In other words, if you import 
std.algorithm.sorting, it'd check that "algorithm" is not a symbol 
defined in the "std" package file (if it exists for std) and that no 
"sorting" symbol exists in the "std.algorithm" package file. That would 
work. But the problem is that if the package file publicly imports all 
of its submodules, then you'll need to parse all the imported files to 
determine if the module you're trying to import conflicts with a 
package-level symbol.

A more practical option would be limit the package files to only two things:

1. a list of modules to import when you import the package (importing 
the package would be akin importing all modules in this list)

2. a list of symbols aliased in the package's namespace (aliased 
symbols can be accessed using the package name as a prefix and through 
selective imports)

Since the list of aliases is stored directly in the package file, 
reading the package file to get the names of each alias is enough to 
tell there is no conflict with the module name when you're trying to 
import it. No need to open the other modules the package refers to, or 
to resolve the symbols the aliases refer to: you only need the name of 
each alias to verify there is no conflict.

For instance, a package file could look like this:

	package std.algorithm;

	// modules to import when a file is importing the package
	// (those are not imported inside this package's namespace)
	module std.algorithm.sorting;
	module std.algorithm.mapping;
	...

	// symbols to alias to this package namespace
	// (importing a module with one of these names is an error)
	alias std.algorithm.sorting.completeSort  completeSort;
	alias std.algorithm.sorting.isSorted      isSorted;
	alias std.algorithm.sorting.partialSort   partialSort;
	alias std.algorithm.sorting.schwartzSort  schwartzSort;
	alias std.algorithm.sorting.sort          sort;
	...

The drawback is that it's hard to maintain the list of fully-qualified 
names up to date if you change it in the various modules. But if the 
goal is only to preserve backward compatibility, creating that list of 
aliases could be a one-time thing. New symbols would continue to be 
imported when you import std.algorithm, but they'd not be available 
directly under std.algorithm: you'd need to use 
std.algorithm.sorting.newSort if you find yourself in a situation that 
requires a fully-qualified name.


-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



More information about the Digitalmars-d mailing list