I believe that we made a few mistakes with Opa, though. The slicer (the component of the compiler that decided which code should be compiled to client and whic hto server) was a great idea, but it came with considerable pitfalls in terms of security. Since then, I have concluded that too much multi-tier magic is actually a bad thing.
If I were to start a new version of Opa, I would probably force developers to split their code manually between client, server, database and location-independent (presumably by putting stuff in distinct directories). This would be much easier to read/audit. But at this stage, this raises the question of whether an entirely new language is really useful. Why not simply do it with a sufficiently smart toolchain based on TypeScript or any language that compiles to wasm?
Source: I did not start the project but I led the design and implementation.
I still remember the sunny day I was at a Starbucks table with a huge americano and my first second-hand MacBook, stumbling upon Opa and thinking "what a great idea!".
It looked so simple, intuitive, and the fact that I could write both front and back end in the same file was amazing!
I never got to do a large project with it, so I didn't notice the pitfalls you are talking about. But I want to thank you and your team for making me understand that web dev does not have to be painful if you choose tools that you like.
While I think that we made some mistakes in the design, I'm surprised that, to this day, there isn't any widely-used language/toolkit/framework [1] that seems to do as well.
[1] Alright, there's GWT, which does pretty well with different tradeoffs. But for some reason, it seems to be extremely niche. The website mentions that "thousands of developers" use it.
1. the model made it hard for the developer to know what data was flowing from the server to the client (e.g. are we leaking a secret as part of a closure?)
2. on the web, you can only (mostly) trust the code that's executed on the server, as the client could have been patched to be running arbitrary malicious code, but the syntax of Opa made it very easy to forget that some of the code was living in this client-side warzone, which in turn could lead to serious security vulnerabilities;
3. when you patch code, especially in auxiliary functions, it's easy to lose track of where it's going to be executed, which means that it's easy to accidentally add a secret leak/capability leak.
We tried many things to reduce the problems, and eventually settled on removing most of the intelligence from the slicer, to make it more predictable, and replacing most of the slicer's tier inference with annotations, to make sure that the developers actually paid attention to the decision. I believe that this wasn't sufficient.
I don't know how much of this applies to Electric Clojure, mind you, that's only my experience from Opa.
Exactly how GWT worked (and still does!). there's a server/, client/ and shared/ directories... but all code is written in Java.
Now that OCaml has gained algebraic effects, I suspect that it should be feasible to reimplement Lwt to use these instead of monads, which should make writing async code much easier, which in turn should make Ocsigen much easier.
I don't know if that's in the books, though.
A COBOL program basically divided into the following four divisions: Identification division. Environment division. Data division. Procedure division.