Open wegendt-bosch opened 5 years ago
+1 for solution (1) and (2.a haskell).
(2.a json) is a bit too much curly braces everywhere. Curly braces make sense to group things together, but when you have only one default statement inside of them, it feels overloaded with braces.
(3) gives quite some degree of freedom to the user. I am not sure if we really want this. You need to derive the default value in runtime as it can be changed everywhere. For me, a default value definition belongs closely to the type definition and is something static.
Introduction
High level language support types that are more defined than numbers, structures and pointers. The most ubiquitous one are Objects. These are structures that carry more semantics and group together functions operating on them. They also support different constructors like a default constructor or constructors that do special initialization.
Some languages then use these default constructors to facilitate common code paths, for example in C++ declaring a variable without an explicit constructor call will call the default constructor, or in Kotlin variables with a nullable type are initialized to null. These are all some kind of default value for types declaring one.
Current Situation
Currently we validate that some types have an explicit initialization, like references, and initialize all other types with some kind of 0. Booleans are false, integers zero, structures are filled with 0, and so on. Sum types per default initialize to their first member with everything set to zero, again, by calling
= {0}
in C, which sets the tagged union to the first enum value and fills everything else with 0.This has been fine for now but a more refined system can be imagined.
Proposal
I propose that types may declare a default value. If they do, users may write variables without initialization:
var i: uint32;
If they don't, there are different cases for a default default value (so the default thing we do for default values):
Product Types
Product types have a default default value if and only if all their member types have default values.
Sum Types
For sum types there are three different strategies to be discussed:
Generated Types
Generated Types have a default if and only if they declare a constructor without any arguments.
Code Example
I propose one of the following ways for declaring explicit default values, all backwards compatible by leaving out the new syntax. Other proposals or better variations are welcome.
Variant 1: Assignment
This variant is the most straight-forward one, but can become cluttered the easiest.
Variant 2.a: Haskell-style properties
In this variant and 2.b types can be followed by a block of properties. This would be forward-compatible with more extensions to types.
In Haskell,
where
is a common way of creating a block of follow up declarations like helper functions, type class instance functions, etc. Recommended style is inline or indented block style.Variant 2.a: Json-style properties
Instead of
where <block>
we could also use some json-like syntax with brackets. This seems a bit more familiar, but is also more confusing since there are two blocks right after one another.Variant 3: Separate declaration
This variant is the cleanest, however it is harder to parse, use, and may create the impression that the declaration is a real statement.
Variant 3.a: Embrace the state
Indeed,
default(type: Kind): type
could be an actual Expression that is read/writeable at runtime, if something like that is desired:This would then be implemented like this: