6 ms·
> We do not have namespaces in C, which means any time we add functionality we basically have to square off with users. Has anyone seriously proposed adding na
by forrestthewoods 4y ago
> We do not have namespaces in C, which means any time we add functionality we basically have to square off with users.
Has anyone seriously proposed adding namespace to C? This feels like an obviously good addition to me. What’s the argument against it?
- raverbashing 4y agoI'm skeptical of it. I think it is a std::opinion::bad_idea() ;)
- mgaunard 4y agomaybe we could call the language with such extensions "C++"
- mort96 4y agoExcept that C++ doesn't serve that role, C++ is its own whole thing. I think "C but with namespaces and a method call syntax (and templates?)" would be a great language which would occupy a completely different space than C++.
- jcelerier 4y agoif you introduce namespaces and method calls you have to introduce name mangling, to differentiate namespace foo { void x(); } and namespace bar { void x(); } and then you have to rely on compiler vendors to use the same mangling everywhere otherwise you end up exactly at the C++ position where there are multiple incompatible name mangling schemes, thus C code compiled with e.g. cl.exe would not be able to call a C function compiled with gcc (and FFIs wouldn't be able to either so you loose the "easy language bindings" "feature" of the operating system ABIs)
- jstimpfle 4y agoNamespaces by themselves aren't a reason why name mangling is needed. There isn't a technical reason why foo::x couldn't be the symbol name, literally. (Not sure what ELF and PE/COFF etc would think of these names in current implementations). Name mangling is needed if you want to overload functions and qualify them only by the types (not names) of their in and out parameters. This is where it gets ugly on the binary level.
- jcelerier 4y ago> There isn't a technical reason why foo::x couldn't be the symbol name, literally. how do you do when you want to access your C function from a language which is binary-compatible with C but uses :: for something else? [a-zA-Z_][a-zA-Z0-9_]* identifiers are the only thing that the whole world more-or-less standardized around. e.g. in fortran you can directly import a C function and call it. But "::" in the middle of a function name would very likely fail (I don't know enough fortran to tell for sure but given how the syntax looks...): subroutine foo (a, n) bind(c) import real(kind=c_double), dimension(*) :: a integer (kind=c_int), value :: n end subroutine foo allows to call a "void foo(double *a, int n);" function defined in C. I imagine that subroutine ns::foo (a, n) bind(c) would likely not work
- zozbot234 4y ago> how do you do when you want to access your C function from a language which is binary-compatible with C but uses :: for something else? Typically you'd do this by picking a different internal name for the function, and putting the external symbol in quotes.
- jstimpfle 4y agoFair point. The C naming convention with flat names is quite conservative and consequently allows the names to be used directly from most other languages without any language-aware mapping / compatibility layer.
- zozbot234 4y agoRust doesn't allow function overloading. Name mangling is used there to implement linking multiple versions of an external module into the final build.
- mort96 4y agoYou do realistically need a kind of name mangling yes, if you want to keep using [a-zA-Z0-9_] as the set of characters in symbol names. But without overloading or other fancy stuff, you could have a super simple name mangling scheme: separate the names by a double underscore "__".
- Jensson 4y agoIn C you can use functions the file doesn't see, and since namespaces changes what symbol an expression refers to depending on what symbols exists in the program it will lead to a lot of strange scenarios. C++ doesn't allow this, and is the main way C++ isn't compatible with C.
- jstimpfle 4y agoNamespaces are often called for especially by programmers used to C++ but doing C. They seem like such a simple feature to implement. I'm still not sure I like them: - What is the benefit of using A::B::C versus A_B_C, really, in terms of avoiding name clashes? I can point out one immediate benefit of doing the latter - code is easier to read because line noise is reduced (perhaps subjective but I think it will be hard arguing the other way around). - Is it a good thing that half the code will now refer to A::B::C using only B::C or even only C? Without assistance of a program with good semantic insight (a solid IDE, etc) this only makes identifier search harder. - Namespaces "enforce" discipline in one way - you can be sure that the symbols at the binary level will be properly prefixed. But with only a little discipline programmers can do the prefixing themselves, and in return they can move code between files (/namespaces) more freely, which is good for refactoring. And as a sibling commenter pointed out, one factor why namespaces get called for could be lack of understanding that we can hide the "guts" of any function (or variable) using "static" linkage. There is less discipline (prefixes..) needed for these functions because they are only visible in the current translation unit.
- pjmlp 4y agoNamespaces can be assigned alias to avoid colisions, good luck doing that to A_B_C.
- jstimpfle 4y agoGood point, but then again I'm not that sure it's a net benefit because I like everything in a codebase to refer to a given object using the exact same name. I suppose aliasing is useful for widely used libraries, for example if a big software projects wants to include two different versions of the same library. Or Team A wants to rename their module but make it easier for other teams that use their module to follow suit. All that can provide some ease of use in the short term but produces more mess to clean up in the long term. IMHO. Real name clashes between two different libraries are quite unlikely, and namespaces would only solve that problem on the source code level, not on the binary / symbol level.
- selfmodruntime 4y ago
- quelsolaar 4y agoYes people have floated the idea. I argued against it, I was asked at the wg14 meeting to explain my position and the following was my reply: I was asked during the meeting why I think that name spaces are a bad idea, so here is my thoughts. I must warn you that the following may sound like an anti C++ rant, because well .... it is. Name spaces have several bad aspects. The majority of them are that they make the code a lot less readable. First, If I see a function call in source code, I cant assume what function is called. There may be a namespace somewhere above or in a header-file somewhere that changes the meaning of the code. It matters a lot for instance when you copy code from one file to another, and all of a sudden the code just means something completely different. Name spaces add state that changes the meaning of the code around it. When your code isn't doing what it should and you are trying to figure out why, you need to be able to trust that the code you are reading on screen is actually what you think it is. I dislike it for the same reason i dislike overloading: it makes it less clear what things you are reading really are. (It may be argued that you already cant trust your eyes in C, because you can do lots of devious things with the per-processor, and to that I say, yes its bad enough, so lets not add more of it) Name spaces splits the identifier in half, but its still a unique identifier. my_module::create(); is and has to be as unique as: my_module_create(); So what are we accomplishing? Do we have the same level of collisions? No, in fact we have more collisions because the parts can collide individually! if there are multiple my_module they will collide, and if there are multiple create in different namespaces they will collide! my_module::create(); // one name space my_module::destroy(); // another name space Collision! how about: using namespace my_module; // namespace with a create using namespace my_other_module; // namespace with a create crate(); Collision! If we instead write plain old C: my_module_create(); my_module_destroy(); No collision. my_module_create(); my_other_module_create(); No collision. Beyond creating new opportunities for collisions, we create confusion by making it possible to hide half the identifier somewhere else. Yes, it can save some typing, but programing is never hard because of typing, programing is hard because its hard to understand what is going on. Namespaces solves the easy stuff, by making the hard stuff harder. Its the age old, trap of C++ of adding something clever out of convenience, that turns out to be unclear and something that the programmer has to manage. Further, namespaces encourage people to use short common names even further, because they think it saves them typing, and they think if it goes wrong they can always manage it with namespaces, and then they end-up having to manage something they shouldn't have to manage in the first place. I have never had a namespace collision in 20+ years of C programming. Why? Because I use long descriptive names, that always start with where the functionality resides. Its readable, straight forward and works. Namespaces is a complicated system for managing a problem that should never happen in the first place, unless the user is very careless. We should not encourage carelessness. I think C, should take some blame for this being a problem because the standard library have far shorter names then is advisable. It has made people think that names like: "jn" or "erf" are good examples of unique, clear and descriptive naming. The added wrinkle of "significant characters" has made people think that C mandates short names, something that no major implementation requires. There also seems to be a persistent belief that display technology has not yet evolved to the level that we can display more then 80 characters per line and that we therefor need to use short cryptic names for everything. This is also an argument from a different age. Namespace collision in C almost never happens between 3rd party libraries, it is almost the exclusive problem of the standard library because it is so poorly named. If we want to fix this, by hiding the standard library behind a namespace, we might as well just add a c_standard_lib_ prefix to all functions, and keep the garbage that is namespaces out of C. Not that we would do either, since both world break backwards compatibility. So why would we add namespaces if it wouldn't be used by the standard lib, the very library we have name collision problems with? In fact if we added an optional namespace for the standard lib, all we would accomplish is to pollute the namespace with one more identifier.
- kevin_thibedeau 4y agoTechnically, they are a part of the attribute syntax in C23. Maybe a backdoor way to get them into a future standard.