Lessons learned ( 2021-11-18 )
Sooooo, we bought an old hospital. Word of advice: don't buy an old hospital if you can avoid it (obviously we tried and failed). It is understandably taking all our energy to get the old into the shape of the new (ie a non-profit art center).
Gather round kids, grandpa's talking
So i am in a pensive mood, definitely reviewing. Maybe it's even the end?
Constant Types
The one thing to come out of this effort is the importance of constant types.
The relation of fourth to third level languages has eluded me for many years, at least in the very succinct form i can express it now. Vague notions that fourth level languages need to be coded in third level languages (wrong!) or need to be compiled down to third level like c++ was into c (wrong too) where floating in my head.
Quite early on i hit upon the importance of Types as a way to describe memory. And the importance of those types being constant or immutable (obvious! but then everything is in hindsight), because otherwise you wouldn't know here is what. Third level languages have evolved the model of types naturally, as all information is available / gathered before the program starts.
A fourth level language has no types (in the sense above), it has classes. Classes (or prototypes, 6 vs half dozen) can change over time. But if one assigns a type to a class, the type instance changes when class attributes are changed.
This essential difference between changing classes and constant types is the difference between fourth and third level language.
The need for speed
Speed was brushed aside for the longest time by dynamic language designers. Luckily things are looking up, more on that below. Interpretation was the easy way, quick to start but slow to get right. We are now at a point where we have to retrofit speed, never an easy tasks. Whereas RubyX shows a compiling approach would not have been difficult, not too difficult for people in the 60's i mean. But as always, the problem was in the head.
Since C is pretty much as simple as can be, it will be difficult to beat in terms of speed before a whole lot of work has enabled cross function compilation and optimization, but i still think it is possible to make code run faster than c, because of just that. Until then we (rather others), will have to build just in time compilers for the instructions that VM's like YARV use.
This process, i am relieved to hear, has started. Not only with the slightly hacky v8. But properly, by Maxime. While working for Spotify, she has started a JIT project based on the idea of collecting and using immutable type data, which she calls BBV. This is very similar to what i was doing for functions, and she had the good sense to narrow the approach down to Basic Blocks (the BB in BBV). The V is for versioning and means producing new types and not changing old, ie having immutable types.
Too late or too early
Maxime says the Self people were onto this same idea too, but even from just her phd i feel quite vindicated. While in so many ways i think that this work has been started way to late, the choices i made (coding in ruby..) probably mean my work is actually ahead of it's time ie too early. But off course hopelessly incomplete.
Maxime says in one video that they will probably have to reimplement parts of ruby in ruby, just so that their jit can perform cross function compilations. Because they too have noticed very early on that with ruby's small functions, cross function optimisation is going to be essential (more vindication).
Imho no decision is the best decision, and since i don't have time to do any work on ruby-x, i won't :-) Having learned about Maxime and her teams effort, seriously funded, well accepted, i will sit back and watch the show. And assume (like in a Disney movie) that the happy end is on it's way.
The icing: Quajects unravelled
Just because i got some 404's from the synthesis thesis (which i consequently cleaned up and linked in), i touched on the Quajects again and finally got it.
Quajects are "true" objects in the sense that they combine code and data in their memory representation. "Normal" objects, implemented by any oo language, are really only data. Their code is pointed to, not really part of the object, more of the class. Off course you could argue that a class is an object, but while that is true, it does not argue the point. As the code for the class is again in it's class, and not in the object.
Another way to look at Quajects is that they are a partial evaluation of an original function (that is not present in synthesis). Ie if a normal OS gives you a file descriptor and a read method that you then pass the descriptor to, Synthesis gives you a quaject that reads only that one particular file. Thus partially evaluating a general read with respect to the given file descriptor.
But while i say "true" object, there is the control flow aspect of Quajects that has not made it into any higher level programming language. The closest we got was the goto (shudder), but the quaject way is more like setjump (more shudders, as both are not named/abstracted). I had a rambling about that some while back, basically saying that we would have to model not just functions (that always return to the same point), but also callouts (ie calling code that is not intended to come back) and callins (places where other code can land without expecting to be returned to). This is pie in the sky off course, but it is where Alexia Massalin was at, already in the 80's. Hat off.