4 ms·
Continuation-passing transforms are very common in compilers. There used to be debates about whether it's better/worse than static single-assignment (SSA), but
by chriswarbo 3y ago
Continuation-passing transforms are very common in compilers. There used to be debates about whether it's better/worse than static single-assignment (SSA), but they later turned out to be formally equivalent :)
The lack of tail-calls in "mainstream" systems (i.e. the ones I get paid to use) is certainly very frustrating. Functional programming ideas are getting more popular, but some of them can be hampered by lack of tail-calls (e.g. using abstractions like Monad is reasonably common in Scala; but naive implementations will cause stack overflows due to the JVM's lack of tail-calls).
Hygenic macros and algebraic effects aren't common in existing languages (although the latter is often provided by libraries; again, I've noticed this creeping into the Scala world), but I've noticed that many (possibly even most) new programming languages have one or both of these. Indeed, regarding algebraic effects: about 10-15 years ago it was common to see languages created for algebraic effects (i.e. someone wanted algebraic effects, so they made a language which has them); whilst these days it's common to see languages "default" to algebraic effects (i.e. someone wants to explore an idea, so they make a language for that; their language does I/O using algebraic effects, because what else are they gonna do‽). I see that as a sort of consensus, that those are the "correct" way to go; if backwards-compatibility isn't an issue.
"Delimited control" is definitely mainstream. Unfortunately most languages seem to implement some weak, ad-hoc form (try/throw, async/await, for/yield, early return); then later have to add more; then more; rather than just implementing the full thing to begin with (e.g. shift/reset, or equivalent).