6 ms·
And yet, people are building big code bases on top of both C and Go without generics all the time. Like C, Go lacks support for elaborate abstractions. It's sti
by codr7 7y ago
And yet, people are building big code bases on top of both C and Go without generics all the time. Like C, Go lacks support for elaborate abstractions. It's still a better C for many problems.
- Gibbon1 7y ago> Like C, Go lacks support for elaborate abstractions. You can build any abstraction you want in C.
- codr7 7y agoI am aware, and the same is mostly true of Go.
- jcora 7y agoYeah, you can write a compiler for a better language. This is disingenuous. Show me Pi types in C.
- codr7 7y agoWord. Interpreter, but close enough :) https://github.com/codr7/g-fu/tree/master/v1 https://github.com/codr7/g-fu/tree/master/v1
- jcora 7y agoThis just isn't what people mean by "writing an abstraction in the language".
- codr7 7y agoI know quite a few who would consider that an option. Embedding a higher level language that's controlled from a more primitive host language allows solving many otherwise tricky problems without the struggle.
- MiroF 7y agoReimplemented generics are all over any C codebase you might lion at.. I mean just look at the Linux kernel
- Crinus 7y ago> Pi types in C. I took a quick look at what these are. Couldn't they implemented with macros like (this builds a type "Utf8String" which "depends" on the value of the "ENCODING" parameter to figure out what set of functions to call for the guts of the functions that handle the type, e.g. RawStringUtf8Length): enum Encoding { Ascii, Utf8, Utf16 }; #define TYPENAME Utf8String #define ENCODING Utf8 #define CHARTYPE char #include "stringdef.ph" Then in stringdef.ph (ph=parametric header, just came up with it): typedef struct { size_t len; CHARTYPE* text; } TYPENAME; #define MAKEFUNC(name) TYPENAME##name #define RAWSTRINGFUNC(name) RawString##ENCODING void MAKEFUNC(Create)(TYPENAME* str); void MAKEFUNC(Destroy)(TYPENAME* str); void MAKEFUNC(CreateFrom)(TYPENAME* str, const CHARTYPE* text); /* this goes in a single C file, single header library style */ #ifdef IMPLEMENTATION void MAKEFUNC(Create)(TYPENAME* str) { ... } void MAKEFUNC(Destroy)(TYPENAME* str) { ... } void MAKEFUNC(CreateFrom)(TYPENAME* str, const CHARTYPE* text) { str->len = RAWSTRINGFUNC(Length)(text); str->text = RAWSTRINGFUNC(Duplicate)(text); } #endif #undef MAKEFUNC /* cleanup input parameters so includers wont need to do it */ #undef CHARTYPE #undef ENCODING #undef TYPENAME Then you can use the above simply like Utf8String u8s; Utf8StringCreateFrom(&u8s, "foo..."); It isn't exactly pretty, but seems to do the work. The ENCODING parameter is only conceptually an Encoding enum, but this can be enforced with some dummy (unused) code that does use of the ENCODING value as Encoding (and if extra strength is needed, as enums are weakly typed, instead of native enums, you could define macros that create stronger "enums" out of structs).
- giornogiovanna 7y agoPeople have probably reinvented generics thousands of times in C, mostly using function pointers or macro hacks. Edit: And the intrusive data structures commonly used in C are way more complicated than the equivalent generic code (in my opinion). https://lwn.net/Articles/184495/ https://lwn.net/Articles/184495/
- codr7 7y agoYou can write Fortran in any language, these people are missing the point. The simplicity is a feature, it also allows you to say exactly what you mean without sweet talking the compiler.
- giornogiovanna 7y agoWhat should I do in Go or C if I want a red-black tree? As far as I know, my options are: - Download one that uses interface{} / void pointers - okay, but not very efficient or type-safe. - Download one that's intrusive - okay, but pretty convoluted. - Write my own - a pain. - Code generation - generics but worse. (This isn't sarcastic.)
- foldr 7y agoWell, your list does include three practical options. Using interface{} is the go-to option and usually works fine. The overhead of interface{} isn't as high as people sometimes think. You have the overhead of boxing the value, but the actual type checking is just a single comparison and jump.
- sacado2 7y ago> You have the overhead of boxing the value, but the actual type checking is just a single comparison and jump. This is way too much in a tight loop. I want my structure to fit in the cache and I want to have as little tests as possible.
- 7y ago
- apta 7y agoAnd thru end up using clunky told like code gen to make up for the lack of generics and for mocking purposes. the resulting coffee ends up being a mess, and ironically, introduces more layers of abstraction (unnecessary interfaces just for the sake of mocking) than code bases in Java and C#