5 ms·
It is a bit sad that an entire blog post is required to explain type declarations in a language as common as C. It is even worse that C++ stuck with it. It more
by delta_p_delta_x 2y ago
It is a bit sad that an entire blog post is required to explain type declarations in a language as common as C. It is even worse that C++ stuck with it. It more atrocious still that C decided it was good syntax to attach operator* to the name instead of the type to justify this crazy business, which thankfully C++ reversed a little with `auto` and West const.
Imagine how much easier that last example would be with a trailing return type, Ptr<> and Array<> parametrised types, and lambda-esque function objects instead of function pointers:
char * (*(**foo[][8])())[]
versus
let foo: Array<Array<Ptr<() -> Ptr<Arr<Ptr<Char>>>>, 8>> = ...
It's immediately clear what the top-level type of `foo` is: some parametrised `Array`. We can do better, though.
In this hypothetical language, one would probably dispense with 'pointer to char' and 'pointer to array' and replace them with view/range/span types, eliminating a layer of type parametrisation and many classes of bugs:
let foo: Span<Array<Ptr<() -> Ptr<Arr<StringView>>>, 8>> = ...
Though I am dumbfounded by why there needs to be a 'pointer to array' in the function return type, and a 'pointer to function pointer'. I assume these are unknown arrays themselves, which means...
let foo: Span<Array<Span<() -> Span<Arr<StringView>>>, 8>> = ...
A perfect language would probably have multi-dimensional spans, which would eliminate the two `Span<Array<>>` and replace with some `MultiSpan<>`.
Addendum: https://cdecl.org/ https://cdecl.org/ is a very useful and very self-aware resource: 'C gibberish ↔ English'.
- neonsunset 2y agoSpan<T> is pretty much C# syntax :) (Also funny, multi-dimensional spans are coming in the form of TensorSpan<T>)
- delta_p_delta_x 2y agoIndeed. Very inspired by .NET, C++, and Rust.
- Quekid5 2y agoIn C++, you can do much of what you want with std::array, std::mdspan... and you could also create a Ptr<T> with "using" to define a type alias for T* -- see [0]. Of course the default syntax for pointers is T* and that's not going to change, so it'll be an uphill battle to keep consistent in any codebase. (I guess systematic use of a rule in clang-tidy or such could help with that.) [0] https://en.cppreference.com/w/cpp/language/type_alias https://en.cppreference.com/w/cpp/language/type_alias
- delta_p_delta_x 2y agoIndeed, and there's `std::function` (albeit not being a zero-cost abstraction; I believe `std::move_only_function` and `std::copyable_function` in C++23 and C++26 respectively are replacements) and lambda statements. But C++ decided the bracket salad `[](){}` was the best way to write lambdas, and I'll never forgive the standard for it.
- kccqzy 2y agoAny sort of type erasure on functions will have a non-zero cost. That's why the only zero-cost abstraction is having a template parameter (such as remove_if), but these come with a code size cost instead.
- optymizer 2y agoimo anything beyond Array<Something> should usually be aliased to help with readability. Array<Ptr<(Int, String) -> Bool>> Should be: Array<OnClickCallback> Applying that to C code keeps the insane decls in check, especially when using function pointer types
- tempodox 2y agoWest const is a travesty given that either side, or both, of a pointer can be `const`. And with refs I prefer to see that something is a `const &` in one place instead of scanning 3 km of template argument list to find that out.
- delta_p_delta_x 2y agoAhh, what a typo. I meant East const: https://hackingcpp.com/cpp/design/east_vs_west_const.html https://hackingcpp.com/cpp/design/east_vs_west_const.html
- BearOso 2y agoI've never seen anything that complex in my experience, and it would be considered bad code pretty much everywhere. Rule #1 of programming is to make code easy to understand and self-documenting. This should be a sequence of typedefs with self-explanatory names followed by a function call taking one pointer or type and returning another.
- uecker 2y agoJust create typedefs or use typeof. One could wrap this in #define _Ptr(T) typeof(T\*) #define _Array(T,N) typeof(T[N]) _Ptr(_Array(int, 8)) x = ... and one can also define view and span types in C. No hypothetical language needed. But I do not think this is an improvement.
- nuancebydefault 2y agoStill, C syntax is 100 times easier to remember than things like templating, smart pointers, dozen flavours of initialyzers in C++, which is used continuously as well.