Please see the disclaimer.
Before I built my
bc, I spent time trying to build a graphical
programming language. While I have since learned the error of trying to do that,
I learned a lot, and more importantly, I made some useful libraries in C.
My most useful library is Dyna, a library of dynamic data structures. I started this library because I missed the C++ STL, and I did not want to write in C++.
Dyna vs the C++ STL
Unlike the static, compile-time template expansion of STL, Dyna works by allowing the user to set, at runtime, sizes and destructors for items. It also treats items as bags of bits; to Dyna, there is nothing special about items themselves.
When I was building the user interface library, called Wima, for the
graphical programming language, I used Dyna extensively underneath. What made it
awesome was that Wima could use
malloc() in the way that it wanted, and it did
not matter to Dyna.
In fact, Dyna itself has a memory pool, and I was able to put one of those pools into another Dyna container without any special code; I just needed to provide the memory pool’s already-existing destructor to its container.
It turns out that if I had used the C++ STL, I would not have been able to use special allocators, like Dyna’s memory pool, without a lot of headache because the STL and its templates end up making different vectors, and/or other containers, incompatible with each other if they use different allocators. Dyna does not have that problem because everything is plain pointers.
On top of that, C++ iterators can cause the same frustrations.
Now, Dyna has iterators too, but Dyna’s iterators are (mostly) plain pointers that are translated into indices, incremented, and translated back into pointers. Because of that, with one exception, they can be treated as simple pointers.
Not only that, but plain C arrays are faster than C++ STL vectors, at least according to the posts linked above and my own tests, even though Dyna uses runtime data and STL vectors use templates.
I do agree with most people that Rust has pushed the software industry forward, by leaps and bounds. But I have never wanted to program in it.
The reason is that Rust has different, incompatible pointer types. If you write a function that takes a specific type of pointer, it can’t take any other, without a lot of effort. I recognized early on that this would be a pain point, and while Rust has been carefully designed to avoid that pain as much as possible, it still exists.
That said, Rust’s solution to the memory management problem is a good one, even though it requires incompatible pointer types.
So what does this all mean for Yao?
Well, because Rust’s memory management scheme is still the best ever made, Yao will have it, and thus, it will have different pointer types, like Rust. It will have borrowed pointers, owning pointers, and reference counted pointers. In fact, users will be able to create their own pointer types.
And yet, Yao must avoid the problems that Rust and C++ have. How will I do it?
The answer lies in what kind of pointers create the problems in the first place: different, incompatible pointers.
Obviously, Yao will have different kinds of pointers, but maybe there is a way to make sure that they are not incompatible.
And there is: Yao’s pointer types will have to implement a Go- or Java-style interface, and functions will require that interface instead of a specific pointer type. (Obviously, if a function does need a specific pointer type, it can require that too.)
This means that Yao will have different, but not incompatible, pointer types. For the most part, pointers in Yao will be able to be treated as nothing more than plain pointers while implementing a modern, deterministic memory management scheme underneath.
Because when it comes down to it, users should not have to choose between flexibility and ease of use.