Well, imagine your type-system was able to tell you exactly what roots are mutable in what scope. Now you can run a garbage collection on a single scope.
That's not how it works, but in pseudo code:
collect {
// Some code
return ...;
}
Well, if you don't have a type-system that tells you what is mutable, you have to either scan all the mutable roots, or maintain a write-barrier to know what could have captured data in the scope.
The problem with write-barriers, which is the go-to solution for generational GCs. Is that it is a conservative approach. Meaning, it will promote garbage in the cases where the pointer that lived outside of the scope is dead.
If you use a write-barrier, what is going to happen is that [A, B, C] is going to be promoted, because the barrier is going to track the object myObject, and it doesn't realize that it's dead.
However, instead, imagine you have a type-system that tells you that in that scope, the only thing that can be mutated is myObject!
Well, now you can run that in a loop, without accumulating garbage!
So, myObject and the list are allocated in different generations/scopes/etc, and we'd typically trip the write barrier, if we kept the program as is. Right. I don't see how it follows after, that we can avoid the barrier based on just mutability information. It is true that we can only "capture" data with the involvement of mutable objects, but I am struggling to figure out what more we can derive from mutability information. It feels like I'm missing some inference step between "the only thing that can be mutated is myObject" and "now you can run that in a loop, without accumulating garbage" and I can't think of one.
I would be more tempted as a compiler writer to delete all the code, since nothing is ever read outside the loop; but such analysis again doesn't depend on mutability type information per se, rather on what mutations occur in the program.
If done right, SQLive is the sort of thing that could entirely change the way many applications are written. Solving the problem of real time collaboration at the database level has been a dream of mine for years. Unfortunately I'm doubtful that existing RDBMSs will be able to integrate such a thing, seeing how shoddy implementations of materialized views have been.
I really hope you are successful in tackling this problem and that you can share your work.
I did just that recently. They certainly seem to offer the most complete solution. Definitely worth keeping an eye on.
I had to pass because of its prohibitive license (for now) and the head-scratching bugs I ran into with the direct Postgres source. I also had some concerns about the complexity Materialize would add to architecture of the sort of small apps I typically build.
I know this is unappreciative of the complexity of the problems that Materialize solves, but it would be so nice if Postgres just had observable (with triggers), no-compromise incremental materialized views.
What sort of experiences have you had with Materialize, if any?
Thanks for trying Materialize, (I work there!) What bugs did you run into with the Postgres Source? If you put them in a reply here or an email to andy@materialize.com we would be very appreciative of your feedback.
There seem to be 2 questions here:
1) Is Hack type inference total? Answer no: you must annotate parameters and return types.
It would be pretty much impossible to implement total type-inference without loosing separate compilation in Hack.
PHP projects are not organized around a module system, which means that you have "spaghetti" dependencies, and even better, cyclic dependencies all over the place.
So trying to implement total type-inference would be a bad idea, you would not be able to separate the code in independent entities and the checker would not scale.
2) Does Hack support structural sub-typing? Answer: No, but not for obvious reasons.
Fun fact, the first version of the type-checker was implementing structural sub-typing. And it was not scaling, for subtle reasons.
Hack allows covariant return types, so if we implemented structural sub-typing we would have to "dive" into the return types of each method to see if they are compatible. But in turn, these objects could have covariant return types etc ... The process of checking that was too inefficient. Caching is a bad idea (or at least a non trivial idea to implement), because of constraints and type-variables.
Since disallowing covariant return types was not an option (it was crucial to make a lot of code work), we had to kill structural sub-typing.
I hope this answers your question. As a big OCaml fan myself, I like the features you just mentioned (Well, Hack is written in OCaml), but they really didn't seem to be a good fit due to the nature of the language and the kind of checking speed we were shooting for.
Thanks! I was mostly thinking about point 2, and I understand your motivations in going in a different direction after trying it. Very good and enlightening answer!
Yes and no.
Yes, because TypeScript is bringing a type-system to a dynamically typed language and so did Hack.
No: because Hack is bringing some additional language features affecting the runtime. Modest changes for now, but we intend to carry on in that direction.
The key difference is affecting the runtime. All those typescript features can be compiled down to regular JS and typescript-generated javascript can be run in a browser without extending the JS engine.
I don't know what you mean by that... stuff like classes were already in the harmony proposal phase before Typescript implemented them. Stuff like type hints won't be in JS ever.
At least to date, Microsoft stresses the "TypeScript is just JavaScript." New language features are added to ES6 and then wrapped with types in TypeScript.