views:

225

answers:

8

Why do some languages, like C++ and Python, require the namespace of an object be specified even when no ambiguity exists? I understand that there are backdoors to this, like using namespace x in C++, or from x import * in Python. However, I can't understand the rationale behind not wanting the language to just "do the right thing" when only one accessible namespace contains a given identifier and no ambiguity exists. To me it's just unnecessary verbosity and a violation of DRY, since you're being forced to specify something the compiler already knows.

For example:

import foo  # Contains someFunction().

someFunction()  # imported from foo.  No ambiguity.  Works.

Vs.

import foo  # Contains someFunction()
import bar  # Contains someFunction() also.

# foo.someFunction or bar.someFunction?  Should be an error only because
# ambiguity exists.
someFunction()
A: 

This all depends on your definition of "right thing". Is it the right thing for the compiler to guess your intention if there's only one match?

There are arguments for both sides.

Andrew Grant
+11  A: 

One reason is to protect against accidentally introducing a conflict when you change the code (or for an external module/library, when someone else changes it) later on. For example, in Python you can write

from foo import *
from bar import *

without conflicts if you know that modules foo and bar don't have any variables with the same names. But what if in later versions both foo and bar include variables named rofl? Then bar.rofl will cover up foo.rofl without you knowing about it.

I also like to be able to look up to the top of the file and see exactly what names are being imported and where they're coming from (I'm talking about Python, of course, but the same reasoning could apply for C++).

David Zaslavsky
+1: I like explicitly stating where the name came from. It saves guessing or researching some name for which the language "did some automatic thing".
S.Lott
As I see it, you're arguing against "import *", which is if you like a weak form of the auto-import-from-everywhere the OP is suggesting. Fair enough. But I think what the OP wants to know is, "Since languages already have 'import *', why not go the whole hog and have auto-import-from-everywhere?"
j_random_hacker
Because it would be even more confusing than "import *", that's the point I was getting at...
David Zaslavsky
+4  A: 

There have been languages where the compiler tried to "do the right thing" - Algol and PL/I come to mind. The reason they are not around anymore is that compilers are very bad at doing the right thing, but very good at doing the wrong one, given half a chance!

anon
A: 

The ideal this rule strives for is to make creating reusable components easy - and if you reuse your component, you just don't know which symbols will be defined in other namespaces the client uses. So the rule forces you to make your intention clear with respect to further definitions you don't know about yet.

However, this ideal has not been reached for C++, mainly because of Koenig lookup.

jpalecek
+10  A: 

Python takes the view that 'explicit is better than implicit'. (type import this into a python interpreter)

Also, say I'm reading someone's code. Perhaps it's your code; perhaps it's my code from six months ago. I see a reference to bar(). Where did the function come from? I could look through the file for a def bar(), but if I don't find it, what then? If python is automatically finding the first bar() available through an import, then I have to search through each file imported to find it. What a pain! And what if the function-finding recurses through the import heirarchy?

I'd rather see zomg.bar(); that tells me where the function is from, and ensures I always get the same one if code changes (unless I change the zomg module).

John Fouhy
Not to forget "In the face of ambiguity, refuse the temptation to guess" and "Namespaces are one honking great idea -- let's do more of those!" +1
David Zaslavsky
+3  A: 

The problem is about abstraction and reuse : you don't really know if there will not be any future ambiguity.

For example, It's very common to setup different libraries in a project just to discover that they all have their own string class implementation, called "string". You compiler will then complain that there is ambiguity if the libraries are not encapsulated in separate namespaces.

It's then a delightful pleasure to dodge this kind of ambiguity by specifying wich implementation (like the standard std::string one) you wants to use at each specific instruction or context (read : scope).

And if you think that it's obvious in a particular context (read : in a particular function or .cpp in c++, .py file in python - NEVER in C++ header files) you just have to express yourself and say that "it should be obvious", adding the "using namespace" instruction (or import *). Until the compiler complain because it is not.

If you use using in specific scopes, you don't break the DRY rule at all.

Klaim
A: 

Is it really the right thing?

What if I have two types ::bat and ::foo::bar

I want to reference the bat type but accidentally hit the r key instead of t (they're right next to each others).

Is it "the right thing" for the compiler to then go searching through every namespace to find ::foo::bar without giving me even a warning?

Or what if I use "bar" as shorthand for the "::foo::bar" type all over my codebase. Then one day I include a library which defines a ::bar datatype. Suddenly an ambiguity exists where there was none before. And suddenly, "the right thing" has become wrong.

The right thing for the compiler to do in this case would be to assume I meant the type I actually wrote. If I write bar with no namespace prefix, it should assume I'm referring to a type bar in the global namespace. But if it does that in our hypothetical scenario, it'll change what type my code references without even alerting me.

Alternatively, it could give me an error, but come on, that'd just be ridiculous, because even with the current language rules, there should be no ambiguity here, since one of the types is hidden away in a namespace I didn't specify, so it shouldn't be considered.

Another problem is that the compiler may not know what other types exist. In C++, the order of definitions matters.

In C#, types can be defined in separate assemblies, and referenced in your code. How does the compiler know that another type with the same name doesn't exist in another assembly, just in a different namespace? How does it know that one won't be added to another assembly later on?

The right thing is to do what gives the programmer the fewest nasty surprises. Second-guessing the programmer based on incomplete data is generally not the right thing to do.

Most languages give you several tools to avoid having to specify the namespace.

In c++, you have "using namespace foo", as well as typedefs. If you don't want to repeat the namespace prefix, then don't. Use the tools made available by the language so you don't have to.

jalf
A: 

Interesting question. In the case of C++, as I see it, provided the compiler flagged an error as soon as there was a conflict, the only problem this could cause would be:

Auto-lookup of all C++ namespaces would remove the ability to hide the names of internal parts of library code.

Library code often contains parts (types, functions, global variables) that are never intended to be visible to the "outside world." C++ has unnamed namespaces for exactly this reason -- to avoid "internal parts" clogging up the global namespace, even when those library namespaces are explicitly imported with using namespace xyz;.

Example: Suppose C++ did do auto-lookup, and a particular implementation of the C++ Standard Library contained an internal helper function, std::helper_func(). Suppose a user Joe develops an application containing a function joe::helper_func() using a different library implementation that does not contain std::helper_func(), and calls his own method using unqualified calls to helper_func(). Now Joe's code will compile fine in his environment, but any other user who tries to compile that code using the first library implementation will hit compiler error messages. So the first thing required to make Joe's code portable is to either insert the appropriate using declarations/directives or use fully qualified identifiers. In other words, auto-lookup buys nothing for portable code.

Admittedly, this doesn't seem like a problem that's likely to come up very often. But since typing explicit using declarations/directives (e.g. using namespace std;) is not a big deal for most people, solves this problem completely, and would be required for portable development anyway, using them (heh) seems like a sensible way to do things.

NOTE: As Klaim pointed out, you would never in any circumstances want to rely on auto-lookup inside a header file, as this would immediately prevent your module from being used at the same time as any module containing a conflicting name. (This is just a logical extension of why you don't do using namespace xyz; inside headers in C++ as it stands.)

j_random_hacker