Tags

, , ,

I’m working on modules in Leaf, implementing namespace support. The moment I write my first test a feeling of uneasiness sets in. As I stare at the sample code I see a lot of problems forming. Supporting a C++ style namespace will put a lot of tension in how forward declarations are handled. I’m sure it could be resolved, but do I even need these namespaces at all?

The C++ Namespace

Namespaces in C++ are primarily used to delineate module boundaries, as the language itself has no notion of a module. The function of a namespace is to provide groupings and hierarchies of names. This isn’t the same as merely prefixing all names (the C approach); the hierarchy aspect is important. Consider the below pseudo-code.

namespace a {
	namespace b {
		print(value)
		print(sub::value)
	}
	print(b::value)
}

In fully qualified names, the lookup of ‘value’ will proceed as ‘::a::b::value’, ‘::a::value’ then ‘::value’. The lookup of ‘sub::value’ will be ‘::a::b::sub::value’, ‘::a::sub::value’, ‘::sub::value’. The first namespace match is the winner. It doesn’t matter if the variable actually exists in that namespace. This can be seen with the final ‘b::value’ which will only check ‘::a::b::value’. If there is no variable ‘::a::b::value’ the compiler will produce an error. In this sense, a namespace is also a symbol.

I’ve created some test code at ideone.

C++ also has something called argument dependent lookup. When resolving the names of functions it looks into the namespaces of the type of each of its arguments (simple example). A typical use of this is for operator, and common function overloading. It allows the definitions of the overload to be within a namespace, but not need qualification to be referenced. This definitely helps in creating generic templates, but throw in implicit conversions and partial specializations and it can get quite confusing.

The Python Namespace

Namespaces are created automatically in Python modules. The definitions of a module do not overlap with other modules. An ‘import’ statement must be written to use them. Since modules are explicitly bound to symbols they simply follow the normal name resolution rules.

What troubles me in Python is that typical programs tend to import a lot of names. Obviously you don’t have to do this: functions can be referenced via a module name rather than imported directly. I often find that retaining the module name clarifies the code, but at times can be an inconvenience (especially for longer names). Without truly understanding why these individual name imports are done I’m afraid I’d be forced to also allow the practice in Leaf.

Perhaps a larger issue in Python is the difficulty in making and using a hierarchy of modules/packages. Okay, the making side is easy, but the referencing from other code is difficult. I’ve looked around and found several approaches, but nothing that looks like a best practice. I think this discourages one from using them as often as one should. In contrast, C++ namespaces are quite simple to setup and reference. This aspect in Python is annoying because I otherwise feel as though the general model is correct and may be sufficient to replace namespaces.

Anonymous

I tend to use a lot of anonymous namespaces in C++. These make the names private to the translation unit, of primary importance to the linking phase where they might otherwise conflict. This doesn’t feel like a good reason to require namespaces though. It is a workaround to how the toolchain is working. I’d much prefer that my symbols names are private unless I otherwise mark them for export.

Classes

Object oriented programming also introduces namespaces in the form of classes. Each class encapsulates a set of names specific to that class. We may not always think of it from this angle, but it is definitely a namespace and probably the most commonly used one. Not just for functions, the class namespace is often filled with type aliases, structure types, and enumerations.

Often one finds a class filled with static functions and variables. I find this appropriate only if they are intimately tied to the class. Either they are private support functions, or static identity functions (usually to support templates in C++). A function filled with many public static utility methods is highly suspicious: it looks like an explicit namespace. Would not a module work better?

Something Else?

Between modules, classes, and perhaps even enumerations, I’m not sure if an explicit namespace is actually needed. C++ definitely needs them since it lacks modules and all files share the same global namespace. Is there any other reason why they are required? I’d be interesting in knowing whatever uses you have for explicit namespaces. If nothing comes up, I won’t have them in Leaf.