Two uses for “ref” or another “own” keyword?

My last post was about the supposedly perfect types for a new programming language.

I think I might be onto something here. But I also could be way off.

I personally think that owning pointers and optional/maybe pointers could be much more important than const correctness ever was. Well, if you have a garbage collector, then it’s not that much of an issue, but as I’m talking about something like C++ and manual memory management here, it is a very important thing for bug free code. I bet Rust has the perfect solutions for both of these issues (pointer lifetimes and const correctness), but it seems to be a moving target, and for some reason, I found it a bit confusing. (But I am a very confused programmer: that’s why I’m looking for clarity and simplicity.)

Ok. Let’s get to the details:

val SomeClass someObject

That was a value type.

ref SomeClass someRefObject

Basically a unique_ptr. But you can have links to it. You can’t delete it. It must always exist. You can’t pass it onto another thread. (I haven’t thought about concurrency much.) This must also mean, that you can’t have an opt pointer to it, only a link pointer.

link SomeClass someLink = someRefObject

That’s a link. The rule is: you can’t delete it. It’s just a link. You must check that it exists. So it’s just like an opt, except you can’t new it or delete it. It is just a link to something that exists elsewhere (or doesn’t exist).

opt SomeClass someOpt = null

That is an opt. You can new and delete as much as you want. It is versatile, but leads to having to always check if it is null or not. You can’t dereference it unless you check. So if you want cleaner code, you can use mostly refs and values, if possible. You’ll have to declare it null, if you really want it to be empty.

someOpt?.callSomeFunc

Thank you goes to Apples Swift for this nice syntax. This equals:
if(someOpt) someOpt.callSomeFunc, but it is shorter!

My question today is about the ref type. The sort of unique_ptr or sort of like C++ pass as reference. I’m wondering if it would be more clear to use two keywords or just one keyword with it.
The two use cases are:
1. real refs who actually own their data. Usually members of a class.
2. function arguments passed as refs, who are only guaranteed to not be null, but don’t actually own their data.

Should they both use the keyword “ref”. Or should the first one be “own”, like here:

own SomeClass someOwnObject

func ()someFunc(ref SomeClass someArg, int val_arg)
{
	//delete someArg //can't delete someArg
	//someArg is guaranteed to be always valid.
	someArg.callMe
	//opt myFavouriteOpt = someArg
	//can't pass it onto opt, because then you could delete it!
	
	link butICanLinkToIt = someArg

	butICanLinkToIt?.callMe //and then you must check for it
}

someFunc(someOwnObject, someOtherOwnObject, 42)

//OR should they both just use ref

ref SomeClass someOwnObject
func ()someFunc(ref SomeClass someArg, int val_arg)
{
	//... the same
}

So, which one is more confusing. A new keyword, or overloading the ref keyword to mean two related concepts, that for the most part share the same properties? “ref” keyword would then just quarantee that the pointer exists.

I’m currently opting for just a single “ref” keyword for both cases, but I really like the own keyword too. But it sounds more like a verb than a type.

I think the most important type here is “link”. Because it can hold anything. It can hold opts and refs.

I thought I’d make a sort of a list of the qualities of each type, and how they are connected:

link = ref //ok
link = opt //ok
link = link //ok
link = val //ok
new link //not allowed
delete link //not allowed

opt = link //not allowed, because it could be a ref.
opt = ref //not allowed. Use a link instead.
opt = opt //ok
opt = val //not allowed. Use a link instead.
new opt //ok
delete opt //ok

ref = link //not allowed, except as function args (own keyword?)
ref = opt //not allowed, except as function args
ref = ref //not allowed, except as function args
ref = val //not allowed, except as function args
return move ref //ok. C++ move semantics, but only when returning refs.
new ref //ok, when initializing
delete ref //not allowed. It behaves like a value type.

Why do we need “own”s. Why do we need them? Why do we need unique_ptr’s?
Can’t we just use “val”s to own data. links to link to them safely. refs as function arguments that are guaranteed to exist. And opt’s when we want to make it null or to exist. That would be closer to C++…

I’ll have to think about a use case for “own”.