#include and language design

Started by
12 comments, last by flangazor 19 years, 6 months ago
Just a random thought: In C/C++ and an assortment of other languages you generally tell the compiler, in the beginning of a file, to #include some interface that you would like to access later on, in that same file. When reading some of my prior efforts I sometimes find myself wondering at these inclusions. What function did I actually need this header file for? etc. Concerning language design, I don't think this is such a good solution (as opposed to using fully qualified names.) std::abs( x ); or: cstdlib::abs( x ); Ok, so this example was trivial, std::abs is declared in cstdlib. But generally, this current disparting of reference adds strains on the maintainer of large sets of code. In an ideal world focus would not be so much on the actual file in which something is declared.
Advertisement
Interesting thought. It's something that they're fixing with newer languages (with Java at least, I haven't used C# yet). But you could always just comment out the #include line and see what errors pop up. Sometimes I like to think of my compiler as a "search for all compile errors" tool.
Quote:Original post by Machinoid
Just a random thought: In C/C++ and an assortment of other languages you generally tell the compiler, in the beginning of a file, to #include some interface that you would like to access later on, in that same file. When reading some of my prior efforts I sometimes find myself wondering at these inclusions. What function did I actually need this header file for? etc.

Concerning language design, I don't think this is such a good solution (as opposed to using fully qualified names.)

std::abs( x );

or:

cstdlib::abs( x );


Ok, so this example was trivial, std::abs is declared in cstdlib. But generally, this current disparting of reference adds strains on the maintainer of large sets of code. In an ideal world focus would not be so much on the actual file in which something is declared.


There are a couple of problems with this.

For one, being able to just use a fully qualified name without including the file would imply that your compiler would have some way of knowing where that function or class was declared. This would mean that either every time you add code you'd either have to tell the compiler all of the components of that file, otherwise the compiler would have to parse all of the possible files when you just use the explicit name to figure out where the definition is (which could be an unbelievably huge amount of files and millions or billions of lines of code). As well, in C++ that would break the concept of having simple one-pass compilations.

Also, what happens if you have two files that declare the same function or class, etc. This causes no problems with an inclusion model since you include the file that you need, however with your proposed model you would have ambiguity and therefore an error.
Quote:Original post by databandit
Hi,
I am not really sure, but I think you can use "using namespace <something>" in the place of those . . .


No, you can't. You can do that for namespaces but not for header files in general. And besides, using namespacea is another fine example this disparting of reference.
Quote:Original post by pinacolada
you could always just comment out the #include line and see what errors pop up. Sometimes I like to think of my compiler as a "search for all compile errors" tool.


I wouldn't recommend doing this because one of the headers you include may do something that is implementation specific such as include another file that you need. In turn, you may be able to get rid of compiler errors in your project on your particular compiler with the given implementations, however your code may not work when you switch to other compilers or other implementations.
Quote:Original post by Polymorphic OOP
As well, what happens if you have two files that declare the same function or class, etc. This causes no problems with an inclusion model since you include the file that you need, however with your proposed model you would have ambiguity and therefore an error.


Yes, I know. However, we shouldn't limit our thinking to current languages. Some future language/system, designed for huge amounts of source code, would have to impose namespace collision detection/control. I think today's languages are not qualified for software of that magnitude (of what will some day be required). Just think about what was enough 40 years ago!

Languages will need to evolve.
Quote:Original post by Machinoid
Quote:Original post by Polymorphic OOP
As well, what happens if you have two files that declare the same function or class, etc. This causes no problems with an inclusion model since you include the file that you need, however with your proposed model you would have ambiguity and therefore an error.


Yes, I know. However, we shouldn't limit our thinking to current languages. Some future language/system, designed for huge amounts of source code, would have to impose namespace collision detection/control. I think today's languages are not qualified for software of that magnitude (of what will some day be required). Just think about what was enough 40 years ago!

Languages will need to evolve.

Yes, languages evolve, but the problem is that you probably don't actually want it to do collision checks. If there were collision checks it would make it difficult to have several projects on one system since it is very conceivable that different projects use some namespaces or variables of the same name. That also makes it possible for some code to be valid on one person's computer but not on anothers.

Take for example one person who makes a project on their computer and has a namespace foo and inside a class type called bar. They may be able to make and compile the app on their computer, but if they try to move the code over to another computer who also happened to have a foo::bar, then their program won't compile. With the inclusion model this isn't a problem since you just include the file that has the proper class, however, with your model, you'd be stuck. In turn, people would always be naming their classes and namespaces with non-simple names (or perhaps have to get rid of a concept of naming in favor of randomly generated GUID's), for the fear that someday, someone might want to use their code on a computer that already has their names defined in some random file. Ironically, this is the exact type of thing that namespaces are supposed to solve.
Quote:Original post by Polymorphic OOP
Yes, languages evolve, but the problem is that you probably don't actually want it to do collision checks. If there were collision checks it would make it difficult to have several projects on one system since it is very conceivable that different projects use some namespaces or variables of the same name. That also makes it possible for some code to be valid on one person's computer but not on anothers.

Take for example one person who makes a project on their computer and has a namespace foo and inside a class type called bar. They may be able to make and compile the app on their computer, but if they try to move the code over to another computer who also happened to have a foo::bar, then their program won't compile. With the inclusion model this isn't a problem since you just include the file that has the proper class, however, with your model, you'd be stuck. In turn, people would always be naming their classes and namespaces with non-simple names (or perhaps have to get rid of a concept of naming in favor of randomly generated GUID's), for the fear that someday, someone might want to use their code on a computer that already has their names defined in some random file. Ironically, this is the exact type of thing that namespaces are supposed to solve.


Yes, you're absolutely right. Anyway, this is an interesting problem. Some day they will have to deal with it, because software will probably need to grow beyond what's thinkable today, and the file model will not cut it. The collision-control system would probably just need to isolate extraneous code. File separation is a bit like namespace separation, except that the burden is on the programmer.
Personally, I prefer using modules instead of using #include directives to import interfaces and code into other source files. Python and .NET do it this way, as well as a host of other languages that I don't know about.
The problem is that you introduce language artefacts that are not necessary for problem solving. That is a Bad Thing™.

Quote:Original post by smr
Personally, I prefer using modules instead of using #include directives to import interfaces and code into other source files. Python and .NET do it this way, as well as a host of other languages that I don't know about.
There's nothing inherently wrong with the #include mechanism. The problem is C and C++'s requirement of forward declarations, which have influenced the way preprocessors are written. Coupled with a largely single-pass build process, the result is a bit of a mess.

This could be cleaned up transparently with no language alterations. I've considered doing it as a proof of concept, but I'm too lazy.

This topic is closed to new replies.

Advertisement