No, I too am talking about a hierarchy of internally consistent knowledge.
Have you implemented a compiler or a interpreter for a popular language? I could be wrong but I strongly suspect you haven't. If you have ever implemented a compiler you understand the language at a fundamental level and when stumped with a bug or a highly technical puzzle or what have you - you get that "aha" moment where its like "Ofcource ! How else could it be. This language feature must be using this construct because of X or Y reason and the compiler has to work this way because this part here doesnt allow for it to work any other way, etc ,etc and the optimizer has xyz amount of scratch registers so abc condition could never happen, and on and on."
My comment was talking about a stronger kind of consistency, maybe "inevitability" would be a better word for it. You could make many different tiny changes to the rules of C and still end up with a workable programming language. (Many people have done that, there are tons of languages derived from C.) You could say that the rules of C are "random" - after learning the first n rules, you cannot use logic to predict the n+1st. So learning the rules of C is more about memorization than logic. Math is different: when you learn a piece of math, you know exactly how it follows logically from the pieces you learned before, and you know it couldn't be any other way. That's why it feels more reasonable to me to inquire about math, rather than the details of C.
On a planet far away they have universities. In those universities they have many of the same subjects we teach here, such as math, biology, philosophy, history, computer science, psychology, and literature. But although the subjects of the classes are the same, the contents are different. They teach a history class, but their history is different from ours. So are their biology and literature. I’m not interested in subjects where their content is different from ours.
In some classes, though, the content is the same. They’re teaching the same physics class (assuming they’re at the same level of understanding we’re at) and the same math classes (with a different base). In computer science most of what they teach is different, but their theory of computation is surely the same. Their biology is different, but their teaching of evolution is the same. Their philosophy is vastly different (think how different Eastern and Western philosophies are on earth), but their philosophy of science is probably very similar.
Even if this point of view doesn't make sense to some people, I subscribe to it because it's very inspiring to me. YMMV.
>You could say that the rules of C are "random" - after learning the first n rules, you cannot use logic to predict the n+1st.
You're mis-applying things here. The language is not something to be theorized by itself. Like any (edit:spell) other body of knowledge, it has its own set of initial axioms and the 'C standard' which defines the language is simply a collection of rules other meta-knowledge which are based on those. In that sense it is internally consistent. Thats what I meant.
Yes, you could say that the C standard is a formal theory. It won't be a very interesting one to a mathematician though, because it's huge and describes only one thing, C. There are no special considerations to single out that theory from a huge pool of similar ones. It's like devoting your life to the study of one particular differential equation with a thousand terms, which was written by a committee. Why not the other equation which has a minus instead of a plus over there? Why not study differential equations in general?
Compare with a formal theory like PA, which fits on a page and describes the natural numbers. Proving a theorem about PA has implications everywhere, because natural numbers are everywhere. Or if we want to talk about computation, there are many formal theories with short descriptions that have much more to say about computation in general.
I am not against your POV ! I think we largely agree on most things here. I wanted to correct what I perceived to be a mischaracterization of my 'off the cuff' analogy.
Yeah, from your reply to patrickmclaren I understood the point you were trying to make, and I agree with you. Sorry for misunderstanding you so persistently.
Can you deduce the majority of the C language from these initial axioms?
You misunderstand the usage of consistency regarding mathematics. It is not the same. These rules which compose C are design decisions, and whether they are entirely artificial. Mathematical consistency arises from imposing axioms, following which there are no decisions to be made.
>Can you deduce the majority of the C language from these initial axioms?
Well, no. You can deduce A language but it might not be C.
I sense we're going down a fruitless path here. In my first post I was only giving an analogy of someone understanding math at a fundamental level to someone understanding a programming language at a fundamental level and how they could inform similar abilities/prowess in people when it comes to dealing with complex problems/etc.
My guess you apply your experience with some bizarre language (PHP?) to C, which you never learned. C and C++ are internally consistent in the same way a math theory is. Many programming languages are not, indeed.
> You could make many different tiny changes to the rules of C and still end up with a workable programming language. (Many people have done that, there are tons of languages derived from C.)
Coincidentally, same is Math. I give you Euclid's Fifth postulate as an example.
>You could say that the rules of C are "random" - after learning the first n rules, you cannot use logic to predict the n+1st.
This depends on how do you enumerate these rules. If you learn that auto variables are allocated on the stack it's easy to predict that you cannot return their addresses and there are not going to be default initializes for them.
Saying that C++ is internally consistent at all is a huge exaggeration. Actually I'd be very careful with stating it is more consistent than PHP. Both have many sharp-edges and in both there are plenty of features that feel "tacked on" and are non-orthogonal to each other. E.g. why I can't make a generic (template) function virtual or why I cannot overload some overloadable operators to have exactly same semantics as the builtin ones.
You can't make a member function template virtual because it's just a template, the function doesn't exist until it's statically instantiated. Instantiation can happen across units of compilation, making it impossible for the compiler to generate a vtable with all the instantiations within it. It's not a "tacked on" feature/limitation at all, and I don't see how any statically typed language that allowed function overloading could really work around that issue.
I'm not sure what you mean about the operator overloading thing.
This was a rhetoric question. I perfectly know why I can't do that in C++. C++ does not allow this because of particular generics implementation (done by static compile-time macro expansion), not because those two features are inherently contradictory. In fact, they are completely orthogonal and Java/Scala/C# have no problems with that, despite being statically typed.
As nly pointed out - the virtual template function just does not make sense if you understand what it is. As for the operators I'd guess you mean && and ||? You cannot make them shortcut because the user defined operators are just functions and functions in C++ do always evaluate their arguments.
Virtual generic functions do make sense and many languages allow them. The problem is C++ implements them by compile-time macro expansion (called templates), which renders them impossible.
Template types are also not really first-class members of the type system. The compiler can't really reason about them, it only type-checks them after expansion, when all the genericity disappears. This is completely different than the fail-fast approach in Haskell or even Java, where the code is type-checked at the generic level.
Don't get me wrong - templates is an awesome, extremely powerful feature of C++, but it doesn't play well with the rest of the language, and really feels tacked-on.
Sure, generic functions are awesome when you don't care about performance. This is why C++ does not have them. If you knew nothing about C++ and somebody told you "here, we have a language with zero run-time overhead, can you guess if we managed to implement generic functions?" what would you say?
Function templates are not generic functions. Same as template classes are not types. They play really well with the rest of C++ but I agree, not so well with the rest of Java or Haskell :)
This is the major problem people nowadays have with C++ - they learn some "practical" high-level language in school (usually riddled with random stuff, judging by how much people here are pissed with my mentioning of PHP) and try to think about C++ in concepts of such a language. Then blame C++ for not being their favorite language.
Don't get me wrong. I am quite happy with this making my skills very rare and expensive, giving me both job security and decent compensation. I also want to thank all the people spreading the "C++ is complex hodgepodge of completely random things so it's impossible to learn" idea :)
Generic functions like in Java/C# can be implemented efficiently and with zero overhead. There is nothing that prevents a JIT compiler to generate several versions of the code optimised for different types at runtime, exactly like C++ does at compile-time. Some VMs already do that to some extent in order e.g. to better inline calls for the generic argument. Still, those optimisations are in their infancy, but the situation improves with every year.
"Don't get me wrong. I am quite happy with this making my skills very rare and expensive, giving me both job security and decent compensation."
Eh? C++ skills are not any more expensive than decent Java/C#/Python/(put whatever mainstream language here) skills. Who told you that? This is supply-demand. There is lower supply of C++ coders, so some may think the prices should be higher, but in fact it is compensated by lower demand. C++ is also still being taught at schools, so those skills are not that rare as, say, Haskell, Erlang or Go.
How do you figure out the types at run time with zero overhead? I guess we have different concept of "zero".
As for the price of my skills - my paycheck told me that. And sure, it could be low demand (there are vacancies in my field, that had been open for years, but I don't really know what kind of demand there is for Python, could be decades for all I care). I am just happy for my compensation and if others have more expensive skills - I am happy for them too :)
Nothing is truly zero overhead. C++ templates are neither, because they create some overhead in code size which is obviously non-free (both space-wise and time-wise). Zero-overhead for me = optimized to the point that noone can notice. There is no problem for a VM to generate 10 versions of a tight loop, every one optimised for particular type, with a switch for the type right before entering the loop, or the whole method, or even a whole call-tree.
We also mean different things by overhead. For me (and the C++ committee) it means something that is done in addition. So for me templates create zero overhead as the do not produce more code than the same, non-template code. In practice, templates produce less code as there is a higher chance to fold common code from the instantiations of the same template than from many handwritten functions.
Comparing to other generics implementations - they do add a lot of code, much more than is really needed to achieve good performance. Sure, some of this code can be reduced at linking stage, but for this to work you need to statically link everything which has its own set of problems (overhead of repeated code in every binary).
IMHO the approach is a great example of premature optimisation: generate 2^N versions then try to fold some similar ones to save space. Much better approach is: generate 1 version and specialize small parts when really needed. Technically, assuming sufficiently smart compiler, both would end up with exactly the same code, performing exactly the same, but the latter solution is preferable for other non-performance wise reasons (like better type checking, ability to distribute binary libraries, faster compile times, etc.).
BTW: I still often find Scala containers to be often much faster than C++ STL. But this is probably for much different reasons than template/generics implementation.
I have lost you. Are you still arguing that C++ is internally inconsistent because it's not doing stuff that Java does? Are you arguing that templates add a lot more code than a VM and JIT compiler and languages with generic functions are as efficient as C++?
In the first case - I fail to see how it follows.
In the second case - our levels of expertise is too far apart to discuss anything. I am not saying you are not qualified, I might be just too out of the loop and missing some dramatic advances in Java, Scala etc.
I guess it's a matter of taste. Almost every time I get puzzled by some design decision in C++, it makes sense at first but then falls apart on closer inspection. The most recent example amused me so much that I wrote a blog post about it: http://slepnev.blogspot.ch/2013/07/printing-int-in-c.html. My experience with Haskell so far has been the opposite, design decisions make no sense at first but then turn out to be really smart.
@cousin_it: I have exactly the same feeling about C++ and Haskell. Another feature of this kind is inability to do virtual calls from constructors / destructors. Sure, the explanation makes perfect sense and leaves you with a feeling that C++ got it right and the rest of the world got it wrong. C++ protects you from accessing not-fully initialized object, awesome isn't it? Unfortunately it gets in the way when using factory methods (which are perfrctly ok to be called from the constructor in other languages) and is a source of subtle bugs.
C++ library is not something that is supposed to be very useful, it's something that is supposed to be available. I, for one, never used that library in my 15 years of professional programming.
Even though the library is covered by the same standard as the language it's not a part of the language and, in practice, is not even available all the time.
@pandaman: Just a minor nitpick about the statement that C++ library is not a part of the language: How come 'new' (builtin language operator, and reserverd keyword) can throw 'std::bad_alloc' (library construct) then? ;)
New itself does not throw, the allocation function does. Nobody makes you use the library allocation functions.
A better nitpick would be dynamic_cast throwing under some conditions. But then, how does it make iostreams the part of the language? There is just a typedef in the std namespace that aliases the type for some optional, compiler specific, data.
I think the point was that mathematics relies on a small set of postulates from which you can derive everything else. Changing a postulate results in a separate system. The same is true in programming languages, but the number of postulates is very large compared to mathematics to the point that their utility is greatly reduced. And also there are so many languages each with its own postulate set that it's really inelegant when compared to mathematics.
Another way to put it is, learning the postulates for langx doesn't provide enough value for many to be worth doing.
>I think the point was that mathematics relies on a small set of postulates from which you can derive everything else.
And I agree, this is one of the assertions my opponent has made. I did not go to refute it because, if not outright false, it's disingenuous.
>Another way to put it is, learning the postulates for langx doesn't provide enough value for many to be worth doing.
This is also true, same goes for everything else. I make money using C - I learn C's postulates. If somebody paid me to use topology - I'd learned topology postulates. What would be stupid if I were paid to use topology but said: "it's hard to learn and it makes no sense for me because I don't like mathematics and don't know any other math discipline so why would I all of sudden learn topology's postulate when I can copy formulas from the net and ask questions on manifoldoverflow.com?"
Have you implemented a compiler or a interpreter for a popular language? I could be wrong but I strongly suspect you haven't. If you have ever implemented a compiler you understand the language at a fundamental level and when stumped with a bug or a highly technical puzzle or what have you - you get that "aha" moment where its like "Ofcource ! How else could it be. This language feature must be using this construct because of X or Y reason and the compiler has to work this way because this part here doesnt allow for it to work any other way, etc ,etc and the optimizer has xyz amount of scratch registers so abc condition could never happen, and on and on."