3 ms·
I recommend C. Once you get the hang of it, it's as fast as writing Rust code (and you don't have to think about borrow checks).
by phendrenad2 5y ago
I recommend C. Once you get the hang of it, it's as fast as writing Rust code (and you don't have to think about borrow checks).
- cercatrova 5y agoYeah, I sure love debugging segfaults. I've used C before and it was cool to learn but I haven't used it since.
- phendrenad2 5y agoOnce you've used C enough, you get the skill to avoid writing segfaults, and when a segfault happens, they're a lot easier to debug. However, since you're just interested in writing a fast command-line app, what about the JVM or .NET? Those have a startup time issue, but once they're running they're very fast, less than an order of magnitude slower than C/Rust/Zig/etc.
- kaba0 5y agoMy biggest gripe with C is not even the manual memory management, since with Valgrind and friends they are not that hard to debug. But how do you solve such a basic issue like having a vector-like data type for different types? Its “macro” system is just a disgusting hack, I could just as well write a sed script instead. And the other option is runtime-overhead or copy-pasting code..
- phendrenad2 5y ago> vector-like data type for different types When using C, if you want something from a higher-level language, usually you'd just do what that language's runtime does internally. So for a vector of heterogeneous objects, you could do a linked-list of pointers to the data objects. Something like: struct VecItm { struct VecItm next; void *data; size_t data_len; char objTypeId; }; Is it more work? Yes. But at this point I would stop and consider if I really need a heterogeneous collection. Do we really need to store a list of objects with arbitrary sizes? What if we have 3 types of objects, in 3 arrays, and we store index into those arrays? struct Foo { unsigned byte x; }; struct Bar { unsigned word x; }; struct Baz { unsigned long x; }; struct Foo foos[256]; struct Bar bars[256]; struct Baz bazzes[256]; // objTypeId: 0 = foo, 1 = bar, 2 = baz struct VecItm { struct VecItm next; unsigned int idx; char objTypeId; }; Or what if we can do something even better? What if Foo, Bar, and Baz all have a max size that isn't too wildly different? Can we store them all in an array directly? // objTypeId: 0 = foo (x contains 8 bits), 1 = bar (x contains 16 bits), 2 = baz (x contains 32 bits) struct VecItm { unsigned long x; char objTypeId; }; struct VecItm vecItms[256]; > Its “macro” system is just a disgusting hack It's really not that bad. It can result in spaghetti-code where your macros are using other macros and they're spread all over a header file. But if you use them surgically, only when needed, they don't cause much trouble. > I could just as well write a sed script The benefit of C macros over sed is if you use some language-aware tooling like an IDE (such as CLion), it will syntax-check and type-check your macros.
- kaba0 5y agoI don’t want a heterogeneous “array”, I want a generic one. Your first example is the overhead I talked about, most high-level languages don’t do this at all. Pointer chasing is really pricey on this level. Your second example misses the auto-growing part. Sure, I want an array, but if that becomes too small, I automatically want to realloc the underlying data to a larger array. And I want to use it for Foo, for int and for any sized objects, generally. C++ can create the proper zero-overhead abstraction over it by generating code for each type I use it for, C to my knowledge can’t do so without copy-pasting code or doing things with runtime overhead, resulting in (often) much slower code.
- phendrenad2 5y agoIn that case copy-pasting is the way, and macros make the copy-pasting much less onerous. This could be messy if there are a lot of types, but I have yet to see a program where having auto-growing vectors of many different types was absolutely essential.