I’m surprised that erlang didn’t get covered. While its not a language people tend to associate with safe it is a language that makes systems that appear to be safe and stable.
Erlang has a very interesting and different perspective on safety; I think I’ve seen it expressed as “let it fail, and recover quickly”. I don’t feel competent to explain it. I can see it being difficult to incorporate in this analysis.
Although it’s a dynamic language, it has a pretty good optional type system (http://erlang.org/doc/man/dialyzer.html) which can be used to catch pre-runtime type errors. It has immutable values and bindings, and no way to get around those, so it’s even more memory-safe than many other currently popular memory-safe languages; you don’t need the compiler to warn you about shooting yourself in the foot, because there is no gun.
From a development safety perspective, it has several safety features, including an application-level exhaustive deadlock detector (http://concuerror.com) which is useful in a highly concurrent language, several different state-of-the-art property testing libraries (QuickCheck; http://www.quviq.com/products/erlang-quickcheck/, as well as open source alternatives, including PropEr (https://github.com/manopapad/proper), Triq (https://github.com/krestenkrab/triq), and others; and a concolic model testing library, CutEr (https://github.com/aggelgian/cuter) which looks quite interesting (using Microsoft’s Z3 theorem prover to explore the execution space and test model adherence). As well as the usual flotilla of testing frameworks and unit testing libraries.
From an operational standpoint, it has a variety of interesting safety stories, to include lightweight runtime debuggability via Recon (https://github.com/ferd/recon), the comprehensive and well-proven OTP supervision library which enables the ‘let it crash’ philosophy, soft realtime granular reduction-counting quasi-preemptive schedulers which significantly reduce runaway process impact, and the list goes on.
I feel like the original post’s criteria are a bit too vague to be scored properly, but from a safety perspective I suspect erlang would score at or near the top of a full lifecycle software engineering project, which is what probably really counts.
I might be inclined to give Haskell and Clojure similar scores on “Prevent deadlocks”.
If you use idiomatic Clojure, you’re unlikely to get deadlocks. It’s not impossible, especially because deadlocks are conceptual rather than a rigidly defined event. You can deadlock Clojure by, say, requiring access to external resources and making the same mistakes. Of course, you can do that in Haskell as well. Haskell’s MVar (much less IORef, which is subject to races) is just lower-level than anything Clojure offers, and not to be used unless you know what you’re doing. It’s not necessarily a fair comparison, because if you’re in Clojure and you need something lower level than what Clojure offers, you end up using Java resources that are no more deadlock-safe than Haskell’s MVar.
Amusingly, none of these languages get +1 on “Ensure List Element Exists”. Data-dependent typing (or, just, dependent typing more broadly) is still some distance from mainstream acceptance.
I’m not sure if you’re singling out MVar in particular, but I was under the impression that idiomatic Haskell uses TVars for anything with interesting concurrency behavior, which IIUC completely prevent deadlock (though starvation can be an issue).
I’m surprised that erlang didn’t get covered. While its not a language people tend to associate with safe it is a language that makes systems that appear to be safe and stable.
Erlang has a very interesting and different perspective on safety; I think I’ve seen it expressed as “let it fail, and recover quickly”. I don’t feel competent to explain it. I can see it being difficult to incorporate in this analysis.
Erlang actually has ‘safety in depth’.
Although it’s a dynamic language, it has a pretty good optional type system (http://erlang.org/doc/man/dialyzer.html) which can be used to catch pre-runtime type errors. It has immutable values and bindings, and no way to get around those, so it’s even more memory-safe than many other currently popular memory-safe languages; you don’t need the compiler to warn you about shooting yourself in the foot, because there is no gun.
From a development safety perspective, it has several safety features, including an application-level exhaustive deadlock detector (http://concuerror.com) which is useful in a highly concurrent language, several different state-of-the-art property testing libraries (QuickCheck; http://www.quviq.com/products/erlang-quickcheck/, as well as open source alternatives, including PropEr (https://github.com/manopapad/proper), Triq (https://github.com/krestenkrab/triq), and others; and a concolic model testing library, CutEr (https://github.com/aggelgian/cuter) which looks quite interesting (using Microsoft’s Z3 theorem prover to explore the execution space and test model adherence). As well as the usual flotilla of testing frameworks and unit testing libraries.
From an operational standpoint, it has a variety of interesting safety stories, to include lightweight runtime debuggability via Recon (https://github.com/ferd/recon), the comprehensive and well-proven OTP supervision library which enables the ‘let it crash’ philosophy, soft realtime granular reduction-counting quasi-preemptive schedulers which significantly reduce runaway process impact, and the list goes on.
I feel like the original post’s criteria are a bit too vague to be scored properly, but from a safety perspective I suspect erlang would score at or near the top of a full lifecycle software engineering project, which is what probably really counts.
Very interesting and informative, thank you!
I wonder if that’s a function of the volume of data available via the GitHub API?
I might be inclined to give Haskell and Clojure similar scores on “Prevent deadlocks”.
If you use idiomatic Clojure, you’re unlikely to get deadlocks. It’s not impossible, especially because deadlocks are conceptual rather than a rigidly defined event. You can deadlock Clojure by, say, requiring access to external resources and making the same mistakes. Of course, you can do that in Haskell as well. Haskell’s
MVar(much lessIORef, which is subject to races) is just lower-level than anything Clojure offers, and not to be used unless you know what you’re doing. It’s not necessarily a fair comparison, because if you’re in Clojure and you need something lower level than what Clojure offers, you end up using Java resources that are no more deadlock-safe than Haskell’sMVar.Amusingly, none of these languages get +1 on “Ensure List Element Exists”. Data-dependent typing (or, just, dependent typing more broadly) is still some distance from mainstream acceptance.
I’m not sure if you’re singling out
MVarin particular, but I was under the impression that idiomatic Haskell usesTVarsfor anything with interesting concurrency behavior, which IIUC completely prevent deadlock (though starvation can be an issue).