Live data from Hacker News

“C is how the computer works” is a dangerous mindset for C programmers

words.steveklabnik.com

301–310 of 387 posts

Re: “C is how the computer works” is a dangerous mindset for C programmers

#301

Earlier quoted context omitted.

A really thought-provoking argument. I suppose that when it comes to choosing "the right tool" the important thing is to optimize globally across the problems that your organization will be solving. But if you want to be able to optimize both globally and locally, well that's just an engineering problem! Two examples spring to mind: 1. Lisp. Lisp's metaprogramming facilities allow you to build the language into the s…

Those programs communicate by serialization and deserialization, usually in bespoke, poorly documented data formats. Unix doesn't put a strong emphasis on protocols. It just says "everything is text, except when it's not". It's not very helpful.

> Unix doesn't put a strong emphasis on protocols. It just says "everything is text, except when it's not". It's not very helpful.

OK, I probably misspoke by claiming it put an emphasis in protocols, but I think it's fair to say that Unix does emphasize component integration by sharing data instead of trying to integrate through a common runtime.

I do think that having everything be (mostly) text is helpful though. It's true that the data formats are often poorly specified, but that is compensated for by the fact text is a format that has a very rich set of tooling. text editors, regular expressions, parser-generators, etc. all make it possible to capture, analyze, and manipulate the text data exchanged.

Perhaps a better example of protocol-based integration would be the internet. It has it's flaws as well, but it's also enabled collective engineering projects on a vast scale.

Re: “C is how the computer works” is a dangerous mindset for C programmers

#302
post #281
post #251

Earlier quoted context omitted.

> most other answers will raise an eyebrow from me Portability. A C library can be trivially linked with any other language. But one will be hard pressed using a python library form Ruby, for example.

Inter-linking is a superpower, as is having a very thin runtime that ships with most operating systems. I realized recently that Python could have saved a decade by having a means to "interlink" modules allowing the use of python 2 modules in python 3. Much easier in the C world; there have been incompatible syntax changes and incompatible link changes BUT not both at the same time.

Embedding Python 2 inside of Python 3 (or vice-versa) is not very hard to do on Linux. Simply `dlmopen` the .so in a new linker namespace and write a little bit of bridging code to interface the two object layouts.

Python has a very rich runtime, so there are some tricky problems to solve if you want this to be perfect. e.g., circular references between the GCs. However, there are simplifying assumptions that can dramatically reduce the difficulty, and these assumptions might not significantly hinder the language-upgrade use-case.

We've known about this approach to embedded interpreters for a couple of years, but we've not found a sufficiently compelling use-case for anyone to develop it beyond a simple proof-of-concept.

In general, it seems like there most compelling use-case for inter-language interfaces is writing core libraries in something fast, (mostly) runtime-free, and portable, especially for codes that no one wants to write twice.

Though I spend most of my time writing codes in slow, rich runtime languages, I've been on the lookout for a better technology to replace C. There are quite a few interesting options, and some have even less of a runtime than (dynamically-linked) C!

Re: “C is how the computer works” is a dangerous mindset for C programmers

#303

Earlier quoted context omitted.

Can you explain?

Rust has both static (based on monomorphization, similar to a template instantiation in C++) and dynamic (based on vtables, similar to inheritance in C++) dispatch: https://doc.rust-lang.org/1.8.0/book/trait-objects.html . Both Rust and C++ are moving in the direction of encouraging static dispatch.

It may be similar, but it is implemented very differently, in exactly the "so can always work on unmodified structures" sense.

Trait objects are a double pointer: one to the vtable, and one to the data. C++'s dynamic dispatch uses a single pointer to a structure that has the vtable and the data. The memory layouts are very different.

Re: “C is how the computer works” is a dangerous mindset for C programmers

#304

One of the blog posts I keep meaning to write is in the vein of "Why C is not portable assembly." Ironically, most of my points about C failures aren't related to UB at all, but rather the fact that C's internal model doesn't comport well to important details about machines: * There's no distinction between registers and memory in C. A function parameter that is "register volatile _Atomic int" is completely legal and…

Don't forget arithmetic operations that can detect various corner cases. Writing something like: sum = x + y; if(sum And then hoping the compiler will optimize your if statment to a single overflow CF check is a bit silly.

That would not prevent the overflow from actually happening, which would be technically UB if the sum is a signed type. It is possible to catch overflow in the last instant like this (in the last instant before executing the addition instruction) but the test is more involved. It's a pity that there are no standardized tools (AFAIK) but it's not possible to write a substantial piece of code in this way, anyway.

What you would generally do is assume that x and y can't be overflow. I.e. you need to have a rough idea what quantities you will process. And put a few checks and assertions in strategic locations.

Re: “C is how the computer works” is a dangerous mindset for C programmers

#305
post #281

Earlier quoted context omitted.

Inter-linking is a superpower, as is having a very thin runtime that ships with most operating systems. I realized recently that Python could have saved a decade by having a means to "interlink" modules allowing the use of python 2 modules in python 3. Much easier in the C world; there have been incompatible syntax changes and incompatible link changes BUT not both at the same time.

Embedding Python 2 inside of Python 3 (or vice-versa) is not very hard to do on Linux. Simply `dlmopen` the .so in a new linker namespace and write a little bit of bridging code to interface the two object layouts. Python has a very rich runtime, so there are some tricky problems to solve if you want this to be perfect. e.g., circular references between the GCs. However, there are simplifying assumptions that can dra…

> Embedding Python 2 inside of Python 3 (or vice-versa) is not very hard to do on Linux. Simply `dlmopen` the .so in a new linker namespace and write a little bit of bridging code to interface the two object layouts.

Where can I pip install this from?

Or is there a reason that none of the huge numbers of python users delaying their transition as much as possible until all their libraries were updated built it?

Re: “C is how the computer works” is a dangerous mindset for C programmers

#306

C is like water. Atomically it is the DNA of all other programming languages. There's a reason why C is generally the fastest language with smaller binaries, and there's a reason why language like Python fallback to C for doing anything processor intensive. C will still be here when the latest fad languages of today are long forgotten.

Not a word of what you just wrote is true.

I think you know better.

Re: “C is how the computer works” is a dangerous mindset for C programmers

#307

One of the blog posts I keep meaning to write is in the vein of "Why C is not portable assembly." Ironically, most of my points about C failures aren't related to UB at all, but rather the fact that C's internal model doesn't comport well to important details about machines: * There's no distinction between registers and memory in C. A function parameter that is "register volatile _Atomic int" is completely legal and…

No support for multiple return values (in registers). There's structs, but that means returning via memory because, well, see point 1.

Return values in registers are a machine level optimization. Whether something is in a "register" is up to the CPU today on most CPUs. If you set a value in the last few instruction cycles, and are now using it, it probably hasn't even made it to the L1 cache yet. Even if it was pushed on the stack. That optimization made sense on SPARC, with all those registers. Maybe. Returning a small struct is fine.

There's an argument for multiple return values being unpacked into multiple variables, like Go and Python, but that has little to do with how it works at the machine level.

Missing operations such as popcount, cttz, simultaneous div/rem, or rotates.

Now that most CPUs have hardware for those functions, perhaps more of those functions should be visible at the language level. Here's all the things current x86 descendants can do.[1] Sometimes the compiler can notice that you need both dividend and remainder, or sine and cosine, but some of those are complicated enough it's not going to recognize it.

Traps are UB instead of having more predictable semantics.

That's very CPU-dependent. X86 and successors have precise exceptions, but most other architectures do not. It complicates the CPU considerably and can slow it down, because you can't commit anything to memory until you're sure there's no exception which could require backing out a completed store.

[1] https://software.intel.com/sites/landingpage/IntrinsicsGuide...

Re: “C is how the computer works” is a dangerous mindset for C programmers

#308
post #171

My favorite take on the severity of the UB problem, https://blog.regehr.org/archives/1520 : > Tools like [Valgrind] are exceptionally useful and they have helped us progress from a world where almost every nontrivial C and C++ program executed a continuous stream of UB to a world where quite a few important programs seem to be largely UB-free in their most common configurations and use cases...Be knowledgeable about…

What is profoundly pissing me off are bunch of hipsters on the internet that are using xyz language and are constantly trying to compare everything to C. We are faster, we are better, we are more portable, we have JIT, we have reflection... and so on. Who cares what your tool for solving the problem is. Use Java, use JS, use python, go, rust... whatever suits for the task. Why do you want to compare yourself to C. Ju…

C is the lingua franca of the programming world. Of course people are going to compare xyz language to C.

Re: “C is how the computer works” is a dangerous mindset for C programmers

#309

Earlier quoted context omitted.

A really thought-provoking argument. I suppose that when it comes to choosing "the right tool" the important thing is to optimize globally across the problems that your organization will be solving. But if you want to be able to optimize both globally and locally, well that's just an engineering problem! Two examples spring to mind: 1. Lisp. Lisp's metaprogramming facilities allow you to build the language into the s…

Those programs communicate by serialization and deserialization, usually in bespoke, poorly documented data formats. Unix doesn't put a strong emphasis on protocols. It just says "everything is text, except when it's not". It's not very helpful.

Modern unix gives you mostly low-level mechanisms, not inter-application protocols. It is better to leave it up to applications/administrators to figure out the best protocol (policy) for their use case, to make the best use of those mechanisms.

Those mechanisms aren't textual, they are byte-sequence based.

It turns out that many text-based protocols are more popular than binary/object alternatives. The penalty for textual redundancy is negligible/acceptable for many of them. Where not, Unix allows people to use unix/create new mechanisms to implement specialized protocols (rpc, protobuffers,...).

Post reply on HN