3 ms·
I don't take the point of this book to be "how to implement an STL-like data structures and algorithms library in C"---although you were his coworker, so maybe
by sfpotter 4y ago
I don't take the point of this book to be "how to implement an STL-like data structures and algorithms library in C"---although you were his coworker, so maybe you know better. I've always viewed it more as "how to build data structures with useful interfaces in C". In the book, the set of libraries presented are an example which illustrates how to approach this using the features that C provides. If you are new to C and don't know how to manage complexity by building up useful interfaces for your data structures, reading Hanson's book is a reasonable way to get some ideas. Another way to go would be to just read through the source of any of the libraries you mentioned, all of which do in fact use ideas which feature in this book. This is obviously not to say that Hanson's book originated these ideas. I also think focusing on the exact style of the code in this book is maybe a bit of a red herring.
- chubot 4y agoYou could view it as an example not meant to be used, sure I'd say it's still easy to get the wrong idea -- the title is "C Interfaces and Implementations: Techniques for Creating Reusable Software" So the claim is that focusing on reuse is missing what C is good for. It's going against the grain; if you want that style, use C++ or Python Those were less viable choices when the book was written, which is another reason I wouldn't recommend this old book, especially to beginners. http://drh.github.io/cii/ http://drh.github.io/cii/ Also the techniques for real long-term reuse involve C ABIs and not C APIs, which are not covered in almost any book, including this one.
- sfpotter 4y agoI'm sorry, I don't completely understand what your point. You seem to be alluding to "what C is actually good for", but it's not clear to me what that's supposed to be. I understand that you think C should not be used to develop generic components that are reused, and that data structures and such should be re-rolled or copy-pasted each time they're used. On the other hand, you do hint that you think C can be used reusably, provided that the ABI is the focus. I agree with this. In my opinion, the techniques discussed in the book are in fact useful techniques for accomplishing exactly this end. If you want reusability the ABI way, what you want is a small surface area which changes extremely slowly. Ideally, you want each ABI to be a subset of the last to avoid breaking changes. OK: accomplishing data hiding via opaque pointers in tandem with a simple, high-level interface is one way to accomplish this, and is the main lesson to be learned by reading this book. (I would argue you really only need to read a chapter or two to learn it, but that's a different story---I would argue that this book is in fact not very good for this reason, but whatever.) If you look at most reusable C libraries, they take this approach. Obvious this book takes a bit of an extreme approach where as much of the details of a data type are hidden as possible, but there is no real reason to do this provided that the details of a type are stable. Then it's OK to expose them as part of the interface. I suppose I take your point that in reading this book, one might get the idea that it's a good idea to develop an STL-style library to use with C and run with that. On the other hand, someone who is learning C might just as well read many books about it (or read lots of code), and be able to contextualize this book well enough to understand that it should be taken with a grain of salt. I think it's also important to point out that there are exceptions to these "rules". GLib is a generic STL-style library written in C which seems to be pretty widely used. At the other end of the spectrum, you have more people (I think mostly in the games community) developing "header only C libraries". YMMV.
- chubot 4y agoThis comment sums it up best: https://news.ycombinator.com/item?id=33142349 https://news.ycombinator.com/item?id=33142349 So basically, use EITHER idiomatic C, which means long functions / few internal interfaces, reuse with ABIs not APIs, bespoke data structures, etc. OR use C++ and ADTs (type safety, abstraction, polymorphism). Or use Rust if you don't need compatibility. So books like CII are of very limited use, especially not for beginners. They will be fighting with the language and not understanding what it's about. ---- To sum it up, C is better for coarse-grained reuse (deep interfaces a la Ousterhout, Unix file system) than fine-grained reuse like CII (hash table, array, set) Related long article I wrote about API (compile time) vs. ABI (protocol, runtime) and related issues: https://www.oilshell.org/blog/2022/03/backlog-arch.html https://www.oilshell.org/blog/2022/03/backlog-arch.html ---- I'll take your point that if you want ABI stability, then hiding layout behind a pointer and not exposing structs is a good idea! Although that pointer's type doesn't necessarily have to be void* as it is in CII -- it could just be an application-specific type Also agree that there are several different ways of using C and C++.
- sfpotter 4y agoWhy is "idiomatic C" equivalent to "long functions and few internal interfaces"? The whole point of having a small surface-area for your ABI with plenty of detail hiding is that you are free to do what you like beneath it. If the code uses a struct named "hash_map" that takes a generic hash function and stores void pointers, but runs fast for my purposes, what do I care? These techniques give you a controlled way to build black boxes. C is a very flexible language, and it is possible to build up quite a variety of patterns in it. Your job as an engineer is to look in your toolbox and select the best tool for the job. Adhering to a "correct idiom" gets in the way of this.