One way is to assume that the user won't import the package; in this case you'd probably name your functions and types in very generic ways. For example your HTTP package would have a REQUEST class, which would be referred to from outside the package as HTTP:REQUEST. People trying to import packages written in this style will eventually run into symbol clashes, and resolving those through shadowing is no fun.
The other way is to design the package for importing. In this case the HTTP package would have a HTTP-REQUEST class, which would be referred to as HTTP-REQUEST from most places (and as HTTP:HTTP-REQUEST in the few cases where you didn't import the package -- but of course you would avoid that because HTTP:HTTP-REQUEST looks ridiculous).
So in that sense it's totally true that a CL-style package system doesn't really solve the problem of name prefixing. It's either going to be part of the name, or it will be in the explicit package name that you'll end up using to refer to the symbol. But who cares? There are other problems that a flat namespace causes, which would actually be fixed by a package system.
> The idea sounds nice in theory, but in practice multiple name spaces do not fit into Lisp very well. Common Lisp packages are an unclean kludge; this was clear to me when I implemented them in the 1980s in the Lisp Machine. It is impossible to use them in the way one would wish to use them. > > In practice, you have to write the package prefix whenever you refer to a symbol that has one. It might as well be part of the symbol name itself. Thus, packages complicate the language definition while providing no benefit. > > So in GNU Emacs I decided to make them part of the symbol name itself and not have packages.
Agree or disagree as you like, but there is a reason: based on his experience with Lisp Machine Lisp, RMS didn't see the point.
While packages may not be a great solution they do at least make the the concept of namespacing explicit and a first class citizen of the language.
Old-style programmers who came of age in the 70's and 80's were absolutely obsessed with keeping the number of characters typed as low as possible. There was a reason for this: the keyboards in those days were terrible. I typed my Master's thesis and my PhD dissertation on VT100 terminal keyboards that had a throw of about 1 cm and required a few hundred newtons to get the damned keys to move at all, much less make a clean contact at the switch. It was more like punching a speed-bag for your fingers than typing on a modern keyboard.
But reducing the number of characters typed is not the only reason for having namespaces, nor is it the most important one. When you add a feature to a language you are saying to the users, "The people who designed this language felt that this feature was important enough to implement so we think it is worth your time to use it." That kind of moral persuasion is not to be under-estimated.
In the case of namespaces, having the feature encourages developers working in that language to think more carefully about how to modularize their code.
This argument may also not be enough to justify the complexity, but when evaluating such things there should be some attempt to cover all the arguments for and against, not just pull out the one you happened to find persuasive.