Live data from Hacker News

What Good Are C, C++, and Java?

danluu.com

31–39 of 39 posts

Re: What Good Are C, C++, and Java?

#31
post #28

Earlier quoted context omitted.

Detailed reply below, but I'm going to agree with the other child and say that you're vastly under-educated in this area and arguing from a point of ignorance. CPU's are not written in a "functional" manner, any similarity is superficial at best and certainly not anything to base practices on. CPU's are relatively, not completely as you so carelessly asserted, bug-free through a development process with high standard…

Thanks for the informative reply. A CPU might not be functional as in Haskell with recursion and types, but it is a weaker kind of functional in the sense that given the same inputs it will return the same outputs - it has no state, and even memory access is just a function to set or read from an address and those functions never fail, never throw null pointer exceptions, etc. Do you disagree that a circuit is more a…

> Thanks for the informative reply. A CPU might not be functional as in Haskell with recursion and types, but it is a weaker kind of functional in the sense that given the same inputs it will return the same outputs - it has no state, and even memory access is just a function to set or read from an address and those functions never fail, never throw null pointer exceptions, etc. Do you disagree that a circuit is more an example of data-flow paradigm than an example of the state-machine paradigm?

This is all kinds of wrong. CPUs have tons of state. Registers, program counters, TLB, CPU mode, cache, etc. You're just abstracting all that state away as "input," Using this criteria, you can say that a C program with a global buffer is stateless because the global buffer is just an input for the functions.

You're incorrect on your mental model of functional pureness anyway. Functional languages have state, it is just that the state is immutable.

> For a CPU to take the next step and decide what work to do at each clock cycle it needs only its inputs - it need not inspect the previous work it did in order to decide what to do next - it simply reads the next opcode the user wants to execute, and does it. That means it is referentially transparent. Which means it's tons more functional than C.

Incorrect. A modern CPU will often look at different stages in its pipeline in order for other stages to progress. This is one of the reasons you have instruction re-ordering. You can also hit a point where you have to flush the pipeline and start your operation over because you had a branch prediction miss.

In other words, CPUs are highly stateful. You are simply incorrect.

Re: What Good Are C, C++, and Java?

#32
post #31

Earlier quoted context omitted.

Thanks for the informative reply. A CPU might not be functional as in Haskell with recursion and types, but it is a weaker kind of functional in the sense that given the same inputs it will return the same outputs - it has no state, and even memory access is just a function to set or read from an address and those functions never fail, never throw null pointer exceptions, etc. Do you disagree that a circuit is more a…

> Thanks for the informative reply. A CPU might not be functional as in Haskell with recursion and types, but it is a weaker kind of functional in the sense that given the same inputs it will return the same outputs - it has no state, and even memory access is just a function to set or read from an address and those functions never fail, never throw null pointer exceptions, etc. Do you disagree that a circuit is more…

Great! I love being incorrect, it's always a good opportunity to learn.

Could you please show me a C program live-diagrammed like the following CPU: http://www.visual6502.org/JSSim/index.html

Since they are basically the same and I was just abstracting away what was convenient to me. Hey, if I'm wrong, I'm wrong.

I think there's a difference. The reason we can make a live diagram like that for CPUs is that they don't care about the "state" they operate, and hence are immune from problems therefrom. C programs care about the state they operate (they take conditional jumps on expressions that might be null pointers) but CPUs don't. Every branch test the CPU runs is for sure run over a register and for sure will either succeed or fail, there's no third choice, no bottom, no chance of it going wrong.

Re: What Good Are C, C++, and Java?

#33
post #30

Earlier quoted context omitted.

Thanks for the informative reply. A CPU might not be functional as in Haskell with recursion and types, but it is a weaker kind of functional in the sense that given the same inputs it will return the same outputs - it has no state, and even memory access is just a function to set or read from an address and those functions never fail, never throw null pointer exceptions, etc. Do you disagree that a circuit is more a…

> it is a weaker kind of functional in the sense that given the same inputs it will return the same outputs - it has no state, I'm trying to imagine what paucity of knowledge about a CPU you can have to say something like "no state." Registers? The program counter? The megabytes of caches? You've got to be stretching the definition of "state" beyond recognition. Each CPU has at least a few dozen, up to a few hundred,…

> You're not talking about a "CPU" here. You're talking about the abstraction that a CPU provides about how it's assembly instructions will be interpreted.

This says it all. No, you are talking about assembly and pretending I don't know about registers. I'm talking about this:

http://www.visual6502.org/JSSim/index.html

In other words, how the CPU takes its steps.

Now that you know what I'm talking about, if you still insist on your point, and if you'd like to help me understand how I'm wrong, which I would appreciate, could you please show me how that live diagram would look like for a C program and its state, since as you say, C programs with its variables and the CPU with its registers are the same kind of "stateful".

A pointer that may or may not point to gibberish is not the same kind of stateful as RAM that is always a list of booleans no matter what happens. That's a pretty strong guarantee. That's a strong type. When in a C program do you enjoy the guarantee that something you are manipulating will always for sure be a certain way no matter what? CPU designers enjoy that guarantee towards registers, program counters, caches, and all the "state" you defend to be so alike that of C. There's a set number of registers and it never changes throughout execution. There's a set number of bits in RAM and it never changes throughout execution. Whether these bits over here and those over there are 0s or 1s are immaterial to the CPU because guess what, the CPU does not care, it does not understand the semantics of my program, and so it can never take a "wrong" step - any "error" is my fault for coding the wrong instructions. (Except for the occasional CPU bug as I have been shown exist).

Please stop trying to talk about assembly. I know assembly. I've programmed Win32 assembly (you can make fun of me, it's fine). I'm not talking about assembly here. I'm talking about the CPU designers or programmers and the guarantees they have when programming that we rarely do in HLLs.

Think of this another way: say you are designing/coding a CPU. Isn't every possible error that can happen your fault? Is that the case in C? Whose fault is it if the computer runs out of memory? If memory gets corrupted? If a hacker pokes your memory to cheat in a game? It's no one's fault, those things can't be predicted. But when designing a CPU you can be sure you have the power to predict every possible thing that can happen in your problem domain. Because you're designing a dataflow grid and an adjunct list of booleans whose semantics are immaterial to you. But in C it's just not possible (nor in any other language, C is just a stand-in here) because you are invested in the semantics.

Re: What Good Are C, C++, and Java?

#34
post #30

Earlier quoted context omitted.

> it is a weaker kind of functional in the sense that given the same inputs it will return the same outputs - it has no state, I'm trying to imagine what paucity of knowledge about a CPU you can have to say something like "no state." Registers? The program counter? The megabytes of caches? You've got to be stretching the definition of "state" beyond recognition. Each CPU has at least a few dozen, up to a few hundred,…

> You're not talking about a "CPU" here. You're talking about the abstraction that a CPU provides about how it's assembly instructions will be interpreted. This says it all. No, you are talking about assembly and pretending I don't know about registers. I'm talking about this: http://www.visual6502.org/JSSim/index.html In other words, how the CPU takes its steps. Now that you know what I'm talking about, if you still…

> Now that you know what I'm talking about,

You don't know what you're talking about. I worked on CPU design teams for 8 years of my professional career. I'm telling you how they're actually built and don't need to use phrases like "CPU takes its steps" as if that's meaningful. Your conceptions about how CPUs are designed, how the design team actually reasons about what they're building, is wrong. It is not correct. You have no evidence this is actually how those people think.

> if you still insist on your point, and if you'd like to help me understand how I'm wrong, which I would appreciate, could you please show me how that live diagram would look like for a C program and its state, since as you say, C programs with its variables and the CPU with its registers are the same kind of "stateful".

I wouldn't venture near such a misguided statement. The closest I'd come would be something along the lines of "At the sequence points of a C program, parallels could be drawn to specific structures in the CPU responsible for tracking that state." Note that those are meaningful words that someone could describe as "wrong" with an explanation, not groping in the dark for "stateful" to be stretched to cover both cases or whatever you were accusing me of doing/not doing. But even then, the entire state of a C program at a sequence point might not co-exist temporally inside a CPU that nevertheless returns a correct result so it would take some more guard language.

> There's a set number of registers and it never changes throughout execution.

This is a prime example where it's really clear you haven't considered a CPU architecture from the last decade or so. There are a set number of architectural registers. Inside the actual chip, because we're considering a window of 40 uops instead of one macroinstruction at a time there are an indefinite number of dynamically assigned registers that may potentially hold the value of one architectural register. Look up "Register Renaming" for yet another tables stakes CPU arch concept you're blissfully unaware of.

This is probably going to keep happening. You really don't know enough about the subject matter to make correct or wrong statements. As is, your statement isn't precise enough to know if you were wrong about physical registers or right about abstracted architectural registers. Note that being "right" about architectural registers means your argument is based on an abstraction instead of implementation. And you really wanted to be talking about implementation.

> Please stop trying to talk about assembly. I know assembly. I've programmed Win32 assembly (you can make fun of me, it's fine). I'm not talking about assembly here. I'm talking about the CPU designers or programmers and the guarantees they have when programming that we rarely do in HLLs.

I mentioned assembly once, in passing as a durable layer of abstraction. I also mentioned a whole host of physical reasons why your input/output determinism is false, all of which are equally as devastating to your argument as the one comment you've zeroed in on for no particular reason. I'd appreciate at least acknowledging that something as finicky as a PLL probably has to be included in a discussion about modern CPU's. Were you going to address any of that or pretend it didn't happen?

> Think of this another way: say you are designing/coding a CPU. Isn't every possible error that can happen your fault? Is that the case in C? Whose fault is it if the computer runs out of memory? If memory gets corrupted? If a hacker pokes your memory to cheat in a game? It's no one's fault, those things can't be predicted. But when designing a CPU you can be sure you have the power to predict every possible thing that can happen in your problem domain. Because you're designing a dataflow grid and an adjunct list of booleans whose semantics are immaterial to you. But in C it's just not possible (nor in any other language, C is just a stand-in here) because you are invested in the semantics.

You're not holding yourself to precise enough language for this discussion. First of all, in this low level of a discussion using "fault" in the sense of assigning blame introduces needless ambiguity. I would phrase the "hacker poking" example as "if a ring3 process can have write access to" and it approaches something precise enough to be wrong. All of your examples are detailed in the specification for (most?) architectures, so it would be pretty clear if a simulator and a piece of silicon disagreed who was incorrect.

The CPU designers are NOT "sure [they] have the power to predict every possible thing that can happen in [their] problem domain." They're smart enough to know that the space of x86 programs isn't possible to reduce to formalism. Random testing, directed random testing, and a lot of other strategies are in constant use that would not be if that power actually existed. I explicitly brought this up before as being wrong, nice to see you're not even giving me a fair read before charging ahead with your fantasy.

Nobody currently designing CPU's reasons about it as a "dataflow grid and an adjunct list of booleans." This is a complete fabrication on your part. If you have anything from any current CPU architect, designer, or engineer that actually uses this verbiage to describe what's going on I would appreciate a link or two. So far it looks like you've invented it and are willing to push for this broken metaphor instead of admit there might be something you don't know.

If none of this sinks in, consider that CPU's are written in Verilog. Take the Cantor-diagonal proof of C being insufficient to compute all irrationals and feed Verilog into it. Share your answer with the rest of the class.

Re: What Good Are C, C++, and Java?

#35
post #34

Earlier quoted context omitted.

> You're not talking about a "CPU" here. You're talking about the abstraction that a CPU provides about how it's assembly instructions will be interpreted. This says it all. No, you are talking about assembly and pretending I don't know about registers. I'm talking about this: http://www.visual6502.org/JSSim/index.html In other words, how the CPU takes its steps. Now that you know what I'm talking about, if you still…

> Now that you know what I'm talking about, You don't know what you're talking about. I worked on CPU design teams for 8 years of my professional career. I'm telling you how they're actually built and don't need to use phrases like "CPU takes its steps" as if that's meaningful. Your conceptions about how CPUs are designed, how the design team actually reasons about what they're building, is wrong. It is not correct.…

I don't know how to explain myself any better to you. I'm not disputing what you are saying nor your authority. I'm talking about stuff much beneath what you are talking about which is why I can barely address what you are saying.

I'll give this one last shot and provide some links. That's the best I can do.

As Wikipedia puts it, "An entire processor can be created using NAND gates alone". That's a functional program, whether I'm able to convince you of it or not. Whether there are tradeoffs taken in the pragmatic world of manufacturing sell-able CPUs is beyond what I'm talking about. You may know a lot about this which is why I don't dispute any of what you say, but you are not talking about the same CPU I'm talking about. You are talking about real world CPUs which is fine. It's just not what I'm talking about. If real-world CPU designers prefer to use state in their processor design that's up to them - but the nature and essence of a CPU obviates state, as a bunch of NAND gates suffices for one as Wikipedia puts it.

I'll leave some links here if you are interested in knowing the kind of things that led me to be so misinformed. Thanks for engaging in this discussion. I appreciate your assuming I'm ignorant instead of evil. Every logical gates tutorial I have ever read (including the first result in Google for me: http://cpuville.com/logic_gates.htm) says something like "These gates can be combined to make the larger circuits needed to make a computer processor." which as you can understand may lead a lay person like me (just a programmer, not a CPU designer like you) to believe that processors are therefore functional. Clearly I'm missing something, but I'm not sure I know what.

A functionally verified implementation of a CPU: (keywords: VAMP, DLX) http://www.kroening.com/papers/charme2003.pdf

Formal verification of an ARM processor: http://www.cs.cmu.edu/~bryant/pubdir/vlsi99.vishnu.pdf

Re: What Good Are C, C++, and Java?

#36
post #34

Earlier quoted context omitted.

> Now that you know what I'm talking about, You don't know what you're talking about. I worked on CPU design teams for 8 years of my professional career. I'm telling you how they're actually built and don't need to use phrases like "CPU takes its steps" as if that's meaningful. Your conceptions about how CPUs are designed, how the design team actually reasons about what they're building, is wrong. It is not correct.…

I don't know how to explain myself any better to you. I'm not disputing what you are saying nor your authority. I'm talking about stuff much beneath what you are talking about which is why I can barely address what you are saying. I'll give this one last shot and provide some links. That's the best I can do. As Wikipedia puts it, "An entire processor can be created using NAND gates alone". That's a functional program…

> As Wikipedia puts it, "An entire processor can be created using NAND gates alone". That's a functional program, whether I'm able to convince you of it or not.

We're going to explain why you're wrong down below, but a quick note on the logic you're trying to use upon that faulty premise: Just because some processor could potentially be made in a functional manner does not imply that commercial CPUs are done that way. Do you remember why we're talking?

> As a final point, consider that your precious C programs and the C compiler can only run because of the CPU, which was not written in C nor in any Von Neumann language - oh no, they were written functionally, with only logic gates, in a dataflow-oriented way

You weren't talking hypothetical. You were talking about CPU's that people actually use and their relative stability compared to the terrible software that runs on them. It's really obvious to me that this statement, the entire reason I'm here at all talking to you, was not talking about an abstract Platonic CPU. That you're not admitting it was incorrect and retreating to this ridiculous absurdity is boggling. But you've managed to be wrong yet again, so let's not dwell on the past and just dive into that.

> If real-world CPU designers prefer to use state in their processor design that's up to them - but the nature and essence of a CPU obviates state, as a bunch of NAND gates suffices for one as Wikipedia puts it.

NAND gates can be combined in such a way as to retain state. The way this reads, I think you're assuming that since a single NAND gate cannot retain state it must follow that any combination of them cannot retain state?

Look up "D Flip Flop". Made out of NAND alone, retains state. Given how often you talk about functional things, I'm really really surprised you didn't think about the possibility of feeding an output back into an input. The thing you're missing is what combinations are lurking under that description. I don't think you did the slightest bit of imagining or research on those combinations before declaring all circuitry functional.

> Clearly I'm missing something, but I'm not sure I know what.

Luckily we've found it! You thought all circuits were limited to Combinatorial logic. You were unaware of Sequential logic. I hope you will reconsider the nature and essence of CPU's in light of this new information.

Re: What Good Are C, C++, and Java?

#37
post #36

Earlier quoted context omitted.

I don't know how to explain myself any better to you. I'm not disputing what you are saying nor your authority. I'm talking about stuff much beneath what you are talking about which is why I can barely address what you are saying. I'll give this one last shot and provide some links. That's the best I can do. As Wikipedia puts it, "An entire processor can be created using NAND gates alone". That's a functional program…

> As Wikipedia puts it, "An entire processor can be created using NAND gates alone". That's a functional program, whether I'm able to convince you of it or not. We're going to explain why you're wrong down below, but a quick note on the logic you're trying to use upon that faulty premise: Just because some processor could potentially be made in a functional manner does not imply that commercial CPUs are done that way…

Unfortunately that's not it - I'm aware of sequential logic and its dependency on past signals - just like the `foldp` function in functional-reactive programming allows one to depend on past signals. If you think that's stateful, then foldp is a state-manipulating function and Haskell is finally impure: https://hackage.haskell.org/package/helm-0.4/docs/FRP-Helm-S...

You still haven't explained to me how come CPUs are so amenable to verification while C programs aren't. Another example, explicitly mentioning Sequential Logic: http://www.cs.cmu.edu/~emc/papers/Papers%20In%20Refereed%20J...

Finite State Machines are amenable to verification. I think (not sure) that must be the difference I'm trying to convey.

Re: What Good Are C, C++, and Java?

#38
post #36

Earlier quoted context omitted.

> As Wikipedia puts it, "An entire processor can be created using NAND gates alone". That's a functional program, whether I'm able to convince you of it or not. We're going to explain why you're wrong down below, but a quick note on the logic you're trying to use upon that faulty premise: Just because some processor could potentially be made in a functional manner does not imply that commercial CPUs are done that way…

Unfortunately that's not it - I'm aware of sequential logic and its dependency on past signals - just like the `foldp` function in functional-reactive programming allows one to depend on past signals. If you think that's stateful, then foldp is a state-manipulating function and Haskell is finally impure: https://hackage.haskell.org/package/helm-0.4/docs/FRP-Helm-S... You still haven't explained to me how come CPUs ar…

I didn't make a statement about haskell and I'm not interested in parsing definitions that you've shown gleeful disregard for as recently as two posts ago. The 2003 paper isn't using "functional" in your pet manner and I'm not interested in educating such a hostile student. You're clearly reaching for material you don't understand in hopes that I'll be overwhelmed and it's not a good look. If you'd like to pull one of the three (3) usages of "functional" from the 2003 paper and explain how you thought it relevant to your argument I'd be enlightened. If you're just going to come back with a new raft of papers you don't understand from 30 years ago, please save us both the time and spare me. I'm not interested in reading the results of your uneducated googling and teaching you what you found.

CPU's are "amenable" to verification in the same way C programs are. Throw enough human bodies, enough time, enough blood, enough sweat, and enough tears, at the creation of a software object and it will be "verified" to be correct. There's nothing inherent in C programs that precludes them from being put through this stringent process. There's a lot of costing reasons why people don't spend that time and effort on a field-patchable software object that they do on gates costing millions of dollars to permanently etch into silicon, but I never said anything approaching "CPUs are so amenable to verification while C programs aren't" because I don't believe your argument to be true. In fact, I'd argue that something like the MRC proves that C-like stateful procedural languages can be put through the same process and result in something just as durable as a CPU, if we're somehow admitting you've been talking about commercial CPU's instead of the goofy abstraction you claimed upthread.

Are you planning on addressing how architecturally defined registers aren't stateful? That's a concrete example that posters other than myself also zeroed in on. The only argument given so far was pinned on the NAND equivalence being stateless. It's disappointing you didn't deign to address that in between your wild accusations and gleeful misrepresentations about what I've been saying.

Re: What Good Are C, C++, and Java?

#39

Earlier quoted context omitted.

That's the Stroustrup argument - it's everywhere so it must be good! Like dust, or herpes. Your argument is its own counter-argument. Why is everyone running away from C so badly that they are even willing to put up with PHP? That's how much C sucks. The evidence is in everyone making other languages as soon as they can to get away from C. Look at Lua. People cannot even put up with writing their whole applications i…

I give up. You are literally drenched in a dogmatic hate for low-level and far too under-educated to argue with.

It doesn't seem like innguest hates low-level to me. Kind of random question: What do you think of Rust and ATS?
Post reply on HN