1. You want almost all pointer parameters non null.
2. Non-null variables is very hard to fit in a language without constructors.
Approaches to avoid constructors/destructors such as ZII play very poorly with ref values as well. What you end up with is some period of time where a value is quasi valid - since non-null types need to be assigned and it's in a broken state before it's initially assigned.
It's certainly possible to create generic "type safe" non-null types in C3, but they are not baked into the language.
I don't see that as a problem; don't separate declaration from assignment and it will never be unassigned. Then a ZII non-null pointer is always a compile-time error.
That's tricky when you want to write algorithms where you can start with an uninitialized object and are guaranteed to have initialized the object by the time the algorithm completes. (Simplest example - create an array B which contains the elements of array A in reverse order.)
You can either allow declaring B uninitialized (which can be a safety hazard) or force B to be given initial values for every element (which can be a big waste of time for large arrays).
int* pre_foo = null;
... initialize pre_foo ...
int& foo = *pre_foo;Otherwise it's quite straightforward that they have an uninitialized state (zero) and are then wired up when used. Trying to prevent null pointers here is something that the program to do. However, making the compiler guarantee without requiring constructors it is a challenge I don't know how to tackle.
If you want to do that you can always use a nullable type. You can always assign it to a non-nullable type after initialization if you plan on using the aggregate a lot.
Usually you provide a vector type though, which has an underlying nullable array, but maintains a fill-index such that for all i < fill-index it the value is initialized, and then you have two indexing operations; one which returns a nullable type and the other which bounds-checks and returns a non-nullable type.
I think Rust and similar languages fill that niche already, so there is no real need to try to offer that type of alternative.
typedef struct {
foo @*data; //Non-nullable pointer to nullable pointer of foo
size_t size;
size_t fill;
} foo_vec;
void foo_vec_push(foo_vec @v, foo @x) {
if (v->fill == v->size) {
//realloc and zero data
} else {
data[idx++] = v;
}
}
foo @ foo_vec_get(foo_vec @v, size_t idx) {
if (idx < fill) {
return (foo @)(data+idx);
} else {
abort();
}
}
I'm not sure how this constraint makes it "so much of a different language" at all.2. The other option is to disallow declaration without initialization of non-nullable values. If you can't declare an uninitialized foo_vec, then the user can't ever see an invalid foo_vec.
5 \* 2 \* 1 = 10The entire rest of the language is built on pass-by-value using stack values and stack-managed hidden unique pointers. You basically never actually need to use a ref or a pointer unless you're building an interface to a C or C++ library. I having written a 40k line production application with no reference or pointer types anywhere. Almost any case you'd need is covered by simply passing a compound type or dynamic container as a mutable value, where it's impossible to perform any kind of pointer or reference semantics on it. The lifetime is already managed, so semantically it's just a value.
But having them be inside comments is just weird.