Regularity
A number of specific arguments have been provided, but I believe that a more generic argument applies here, and in many other situations: regularity is good.
For example, if we take a (relatively) immature language such as Rust, you'll notice that part of the difficulties for newcomers are that some things are available in some contexts, but not others.
Commas are easy:
// A trailing comma is allowed after the last argument of a function. fn foo(a: A, b: B,); // A trailing comma is allowed after the last argument of a call. foo(a, b,); // A trailing comma is allowed after the last field of a struct. struct Foo { a: A, b: B, }
Generics are getting better:
// A type alias can be generic. type InlineVec<T, const N: usize> = Vec<T, InlineSingleStore<T, N>>; trait X { // An associated type can only be generic from 1.65 forward (yeah!). type Inline/*<T, const N: usize>*/; }
Compile-time callable (const) are still iffy:
// A free-function can be marked `const`, and evaluated at compile-time. const fn foo() -> i32; impl S { // An associated function of a struct can be marked `const`. const fn bar(&self) -> i32; } trait X { // An associated function of a trait cannot be marked `const`. /*const*/ fn baz(&self) -> i32; } // Instead, a trait _implementation_ can be marked `const`, // but only if the trait declaration was tagged `#[const_trait]`. impl const X for S { fn baz(&self) -> i32 { 4 } }
There are good reasons for this -- design and implementation complexity, notably -- however from a user point of view it's jarring. It's a myriad rules to remember.
Regularity, or Orthogonality, as in the ability to apply a concept everywhere it is sensible to, makes for a simpler language to use.
Thus, the question should be: Why would a language not allow X?
(ie, what advantage is there is NOT providing X?)
voidin practice? $\endgroup$voidin C is not inhabited in the same sense: an expression or function has typevoidbut you cannot construct and pass around a value of typevoid. In Rust, a ZST mostly behaves like other types: you can have a value of type()or any other ZST. A!CopyZST has the same ownership semantics of other types. $\endgroup$