Remix.run Logo
▲ wongarsu 2 hours ago

Java and C# famously solve this with a hidden implicit return value for errors: the exception. The current trend in language design is to take the same idea and make it explicit instead, using sum types. Like Rust's `Result`, where the result contains either the normal value or an error, but never both

Of course C++ gives you the option to do any of the above, and still contains insane API contracts

▲qznc an hour ago | parent | next [-]

I would not describe exceptions as return values. Speaking in a C context, exceptions are more like "longjmp" than "return".

▲cubefox an hour ago | parent | prev [-]

Arguably the better solution compared to these "algebraic sum types" (they go by countless different names) are set-theoretic union types, used by a few languages such as TypeScript.

They allow for types like "String or Integer". A function which returns a value of type "A" can automatically also be assigned to a variable of type "A or B", and a function which accepts a parameter of type "A or B" can automatically aldo be passed a variable of type "A". Which is not the case for algebraic sum types, which require somewhat inconvenient wrapping or unwrapping.

Unlike algebraic sum types, set-theoretic union types are also not necessarily mutually exclusive. E.g. a number of type "Integer or Float" could be both. Moreover, set-theoretic types can be generalized to arbitrary Boolean combinations of types, e.g. "A or (B and not C)", possibly involving disjunctions, conjunctions, and negations (since {and, or, not} are functionally complete). That's not possible for algebraic sum/product data types. Though there is no mainstream language yet with a set-theoretic type system that supports negation types.