But can you please explain why you couldn't use existing math (language and compiler) on the bottom layers (1 and 2) before replacing them by your own? That would help me understand the level of your ambition :)
One, as we know from Church-Turing equivalence, lambda and infinitely many other models of computing have the same expressive power. That doesn't mean they have the same practical utility, though.
Lambda in its Lisp incarnation is actually a rather poor substrate for something like a Lisp machine, I think, because it doesn't layer very well. You can define quite a simple Lisp model, but when you want to turn it into a practical Lisp, you don't add another layer - you grow hair on top of the existing layer. You grow a little hair, you get Scheme; you grow a lot of hair, you get Common Lisp.
I've never seen a lambda model (Qi/Shen perhaps a partial exception, but even there the underlying model is not very simple) that layers a complex language on a simple kernel. I think this is because lambda defines abstractions like symbol tables and function calls, which are user-level language features, in the computational model. The bells and whistles get mixed up with the nice clean math.
Another example is the fact that a modern OS should present itself to the programmer as a single-level store, meaning effectively an ACID programming language in which every event is a transaction. So, you're not constantly moving data across an impedance mismatch from transient to persistent storage, each having its own very different type system and data model.
But, if you're building persistently stored data structures designed to snapshot efficiently and remain maintainable, you really want your data model to be acyclic and not require GC. This goes in a very different direction from almost all the dynamic language work of the last 50 years.
Or, for instance, if your system is designed to work and play well in a network world, it really ought to be able to be good at sending typed data over the network. And validating it when it gets to the other side. Your type system ought to be able to do the same job as an XML DTD or JSON schema or whatever. Well... this wasn't exactly a design requirement when people designed, say, Haskell.
I could go on - there's a lot of stuff like this that is built the way it is because it made very good sense in the 60s, 70s, 80s or 90s. But the requirements really have changed, I think.
Can you, for example, spell out what you mean by "you really want your data model to be acyclic and not require GC"? What is cyclic about the "data model" in e.g. Go or Lua?
I can field that one. If a has A reference to B and B has a reference to C and C has a reference to A, then we have q cycle. Cycles play merry hell with garbage collectors and reference count destructors. Languages that force references to be a strict tree or DAG get cheap destruction in return - see C++ without pointers for example - I pop a local object off the stack and it's gone, along with all its children - no non-deterministic GC pause or delay, no Pythonic cycle check. Rust is built somewhat on this principle.
Right. The way I'd put it is: in system software, the iron law is that you don't make the programmer pay for anything she doesn't need to buy.
What you pay (GC) for the privilege of having pointer cycles in your data is grossly disproportionate to the benefit. Yes, there are a lot of things that are O(k) with pointer cycles and O(log n) without them. If what you buy from this optimization is worth the cost of GC, you are doing a lot of these things... a lot.
So "you really want your data model to be acyclic" means, "you want your programming language to forbid construction of cyclic data structures"? So, for example, connected graphs are not objects you can represent?
They do - but arguably being forced to define the distinction between direct hierarchical references, and symbolic links, helps constrain your data model and make it more rigorous.
Note that relational databases don't have back pointers either. All references between tables are symbolic. Last century, people tried to make databases that were general pointer graphs (google "network database" or "object database") - broadly speaking, it was a disaster.
One, as we know from Church-Turing equivalence, lambda and infinitely many other models of computing have the same expressive power. That doesn't mean they have the same practical utility, though.
Lambda in its Lisp incarnation is actually a rather poor substrate for something like a Lisp machine, I think, because it doesn't layer very well. You can define quite a simple Lisp model, but when you want to turn it into a practical Lisp, you don't add another layer - you grow hair on top of the existing layer. You grow a little hair, you get Scheme; you grow a lot of hair, you get Common Lisp.
I've never seen a lambda model (Qi/Shen perhaps a partial exception, but even there the underlying model is not very simple) that layers a complex language on a simple kernel. I think this is because lambda defines abstractions like symbol tables and function calls, which are user-level language features, in the computational model. The bells and whistles get mixed up with the nice clean math.
Another example is the fact that a modern OS should present itself to the programmer as a single-level store, meaning effectively an ACID programming language in which every event is a transaction. So, you're not constantly moving data across an impedance mismatch from transient to persistent storage, each having its own very different type system and data model.
But, if you're building persistently stored data structures designed to snapshot efficiently and remain maintainable, you really want your data model to be acyclic and not require GC. This goes in a very different direction from almost all the dynamic language work of the last 50 years.
Or, for instance, if your system is designed to work and play well in a network world, it really ought to be able to be good at sending typed data over the network. And validating it when it gets to the other side. Your type system ought to be able to do the same job as an XML DTD or JSON schema or whatever. Well... this wasn't exactly a design requirement when people designed, say, Haskell.
I could go on - there's a lot of stuff like this that is built the way it is because it made very good sense in the 60s, 70s, 80s or 90s. But the requirements really have changed, I think.