The ?perfect? types for a programming language

The perfect types for a programming language could be:
val
ref
opt
link
ptr

Here’s why:

I’m trying to hack up a little programming language called Rae.

While thinking for it a while, and skimming through the awesome new book called Game Programming Patterns and it’s chapter on data locality
I came to think that C++ and C has a great use for it’s stack allocated value types: speed.

If I haven’t completely misunderstood the concept, array traversal is much faster when your data is contiguous. If you use pointers or other type of references in many languages, your program will jump between different areas of memory while going through your array of objects. But when you use an array with value types, your data is supposed to be contiguous in C++. This will make your program run faster.

So we want value types. These will be marked with the keyword “val”.

But using value types as function arguments is slow, if the objects are slow, because you’ll have to make a copy of the whole object. Therefore you can use a pointer or even better, a C++ reference. But the notation and the rules are a bit unintuitive, in my opinion. In Java it is nice that function/method arguments are (Java) references, as all Objects are anyway. So Java syntax is nice here (except it is dull to be always checking for null in almost all cases.)

So we want reference or pointer type for function arguments. And for dynamic memory too. These will mostly be marked with the ref keyword.

But we don’t want pointer math for our basic references. That’s why they will be called references, and not pointers. But we’ll still have traditional pointers. (Maybe you’d need to make an unsafe{} area to use them…)

Owning and borrowing is an interesting concept in the Rust programming language. I’ve only very superficially looked at Rust, but it all seems a bit complicated to me. I’d want a bit more flexibility, and a clearer syntax, with less special grammar like ~, @, and even * and & in C++. So we’ll use words, even if it costs some more keystrokes. At least we’ll use shortened words (I believe the word is abbreviations in english!).

But we’ll make it so that a value type of course owns it’s data. I just checked that in C++11 you can use “move” to put a value type into a container (like a vector) without copying it, thus transferring the ownership. This was the thing that always made me avoid value types – being afraid of the copies. And you can also use e.g. vector.emplace() to create an object directly inside the vector. That sounds so great.

I also checked out half of the video on “null being the billion dollar mistake”. So I thought it might be usefull to never default on null. And to have a reference type that is never null (C++ kind of has this, but in a restricted way). And then we’d still like to have a “maybe” or “option” type that can be null, but must be checked before use. The maybe/option type can own memory (owner is usually the creator).
The keyword for a maybe or option would be “opt”.

On borrowing I thought we could make a “link” type reference, which can not own memory. It can be null, so must be checked every time, but it can not destroy memory either, only link to it.

So. Here is the proposed type system that could be good in my opinion. Please comment if you think otherwise, or have better suggestions.

//built in types are value types.
//int, uint, long, float, char, etc. and also string, default to value type.
int someInt
float a_float
string the_string

Button button //defaults to ref on objects.
val Button button_val
//value type. Owns static data on the stack.
ref Button button_ref
//reference. Can not be null. Very similar to value type.
//Use it mostly in function arguments. Owns dynamic data on the heap.

opt Button button_ref
//maybe owns data. null if doesn't own it.
//The only type that you can delete/free dynamic memory.
//But you must always check for null before using it.
//Compiler won't let you use it if you don't check.

link Button button_lnk
//links to data, can't delete it. only borrows data.

unsafe
{
ptr Button button
//C++ pointer. If you need it. Maybe need to use it inside unsafe block.
}

//Call a member or function always with a dot like in D:
button_val.callMe
button_ref.callMe
button_ptr.callMe
//etc.

//dynamic arrays. Internally implemented as std::vectors,
//so we can know their size.
val Button[] buttons_val //in C++: std::vector buttons_val;
ref Button[] buttons_ref //in C++: std::vector buttons_ref;
opt Button[] buttons_opt //in C++: the same as above.

buttons_val.push_back( button_val ) //copies
buttons_val.emplace //creates a new Button by value.

//static arrays. Internally implemented as std::array or boost::array,
//so we can know their size.
val Button[100] buttons
ref Button[100] buttons
opt Button[100] buttons

//C arrays
ptr Button = new val Button[100];

Ok. That’s it. Any comments are much appreciated!