4 ms·
void is the unit type. The fact that it is not constructible is a wart of the language, inherited from C. It would be easy to fix and would simplify a significa
by gpderetta 2y ago
void is the unit type. The fact that it is not constructible is a wart of the language, inherited from C. It would be easy to fix and would simplify a significant amount of generic code.
A function returning bottom cannot return, yet void foo() {} can. In fact it can even return the result of calling other void functions:
void bar() { }
void foo(){ return bar();}
In generic code void is usually internally replaced by a proper, regular void_t unit type and converted back to void at boundaries for backward compatibility.
[[noreturn]] void bar();
would be a candidate for a bottom-returning function, except that [[noreturn]] isn't really part of the type system.
- tines 2y agoThat's a good point. Maybe one could argue that rather than the unit type not being constructible, the wart of C is that functions that return "bot" can still "finish executing without returning". I would almost rather argue that void is indeed the "bot" type, and a function marked with a void return type shouldn't be said to "return void;" rather we should say that it's an overloaded syntax that means the function has no return value at all. Same for "return bar()" there, that's just a false-friend of the syntax for returning a value, just syntactic sugar for "bar(); return;".
- MathMonkeyMan 2y agoI ran into this recently writing some C++20 coroutines. The protocol for delivering values from a coroutine that was previously suspended has two flavors: one for values and one for void. My initial draft just implemented the value version and used a struct VoidTODO {} where void should be. It's too late now. void pointers are used as a pun to mean "type wildcard." If void were a real thing that could have a size and address, that wouldn't work anymore.
- rerdavies 2y agoYes!! Been there done that. Two flavors of EVERYTHING: one to deal with functions that return values; and one to deal with void functions. It's awful.
- sixfiveotwo 2y ago> void is the unit type. The fact that it is not constructible is a wart of the language, inherited from C. > A function returning bottom cannot return, yet void foo() {} can. Or you could say it the other way, that it is the bottom type, and the fact that it can be used as the unit type for returned values is a wart of the language. Furthermore, void* isn't a pointer of the unit type, it's a type for pointers to undefined/unspecified value types.
- LegionMammal978 2y agoA pointer to the bottom type would make even less sense as an interpretation for void *, since such a pointer couldn't possibly point to any initialized value.
- sixfiveotwo 2y agoSorry, I wasn't clear enough: I meant that void is not just a mix of the unit and bottom types, it is also in used for unspecified (unknown actually) types.
- gpderetta 2y agonothing is gained by making void a proper bottom type. It would only break existing code. OTOH make void a proper unit type would be backward compatible and actually make the language simpler both from a specification point of view and in practical terms.
- sixfiveotwo 2y agoI didn't mean that it should be made into a bottom type, even though it sort of looks like it on the surface. I think the original idea was that void meant "unknown", not "empty" or "non-existent": It was all about whether values could be allocated or not (the wart mentioned above). A plain void variable cannot, but a void pointer can be allocated. For functions, they just reused the keyword to mean "no return value" or "no arguments".
- otabdeveloper4 2y agoVoid means "it is a syntax error to construct a value of this type". This is not a type that exists in category theory or Haskell. (But similar to the "bottom" type.) Hence, "void*" - a pointer to something, but it would be a syntax error to derefence this pointer.
- gpderetta 2y agoIn that regard void behaves like any incomplete type. In C and C++ you cannot construct objects of incomplete types nor you can assign through pointers of incomplete types. But you can construct pointers to void and other incomplete types. Differently to other incomplete types void has some special behaviour: you can declare a function as returning void and return with no arguments is also special cased. You can also cast to void. A void with proper unit semantics would simply be a complete type instead. The only special case would be return with no arguments implicitly returning a void instance, but that would be pure sugar.