Zero evidence that this is the case.
I can tell you that debugging a compiler written in ML is a dumpster fire compared to debugging a compiler written in C++. If take C++ over any FP language for compilers any day of the week.
Zero evidence that this is the case.
I can tell you that debugging a compiler written in ML is a dumpster fire compared to debugging a compiler written in C++. If take C++ over any FP language for compilers any day of the week.
It’s all feels
People who like rejecting this kind of stuff as 'feels' are ironically also being guided by their 'feels'.
There's no scientific experiment you could run that proves, or disproves, that type systems lead to more correctness. It's a thing you cannot possibly know.
This is why I say that people who keep denying this are vibing based on their feels. Instead of asking for the evidence they just keep saying there can't possibly be any evidence.
Better spend some time having fun with std::variant, visit, and ranges transformers.
Depends on the correctness requirements in question. But overall you are 100% correct about this.
FP, among other aspects, enables and promotes some ways of reasoning, for instance when mutation is avoided, that can be relatively easy to use to verify correctness of certain types of properties. For instance, induction proofs and some other kinds of mathematical proofs. However, for some other types of correctness properties, imperative programming can be easier to reason about than FP. One possible example is in regards to implementation of algorithms, where for instance an implementation of quicksort in C is likely to be more concise and clearer than a "true" quicksort implementation in Haskell. Another possible example is (if one assumes that FP requires garbage collection) that of hard real-time systems, for instance some types of medical devices, where even though some types of garbage collection may be viable, approaches like forgoing dynamic memory allocation (no malloc, no reference counting, no types of garbage collection, etc.) may be easier to reason about regarding achieving the correctness requirement of hard real-time.
Overall, I definitely agree that ML and FP are not the best for achieving correctness in all cases.
I personally like to pick and choose between FP and other approaches, and mix them in different ways dependent on the project or task at hand. Like, a purely functional interface with internal mutation in the implementation for optimization. Or, some mutable API that uses FP for some aspects of the implementation where FP is easier to reason about.
> I can tell you that debugging a compiler written in ML is a dumpster fire compared to debugging a compiler written in C++. If take C++ over any FP language for compilers any day of the week.
For larger compilers for some requirements, I could for some projects imagine that this is true. But, for smaller compilers with relatively few requirements, the pattern matching and tagged union features of modern ML languages are very popular, and I like having access to those features when writing smaller compilers. If you do not mind spending the time to expound on this topic, I would very much like to know more. Or, maybe some links, like blog posts, that discuss this topic. I am genuinely curious. A blog post could also be shared elsewhere, instead of just lost in some Hacker News discussion. (Maybe I should start blogging myself).
Also, Hacker News/Ycombinator is censorship-infested.
But larger compilers tend to converge to two architectural features due to the sense that us compiler folk have that it leads to better maintainability. I think there is weak empirical evidence to support these choices (weak because you can’t run a repeatable experiment to prove it; it’s just experience we have)
1. Drop the AST as soon as possible and convert to an IR like a CFG with SSA or something like that. This allows for easier transforms, easier pattern matching, and easier analysis. It’s easier to get the compiler right in CFG than AST and it takes less code to do it.
2. Mutation. Compilers mutate the IR in place. This makes it easier to decouple transforms from one another and encourages writing finer grained passes that just do one thing well.
So you end up with the heart of the compiler being a CFG+SSA IR that is mutable. FP doesn’t help you do that, but OOP does help a lot. And you need state/mutation, ie imperative programming.