4 ms·
> It's still surprising to me that so very few languages have copied this feature (or even independently discovered it). I have often wondered why this is. It
by neurobashing 7y ago
> It's still surprising to me that so very few languages have copied this feature (or even independently discovered it).
I have often wondered why this is. It seems like Lisps did so many things right and here we are in These Modern Times waiting for people to rediscover "the secret is to bang the rocks together, guys".
Are these features just hard to implement in some platforms/languages? Why? Have they been de-prioritized generally until the zeitgeist decides otherwise?
- armitron 7y agoGabriel's "Worse is Better" is still relevant and explains a lot (if not everything). Look at Rust removing CL-style conditions for a good example and Rust is by no means a popular language or a language that makes technical sacrifices in the interest of popular appeal (unlike Python and Javascript).
- KMag 7y agoExpanding a bit on what you're saying, and repeating a bit from another of my comments in this thread, it's vastly easier to reason about exception/condition handling when all of the resources that need to be cleaned up (especially releasing mutexes/monitors) between the exception handler and the exception thrower have been cleaned up. Making stack undwinding the decision of the exception/condition handler is strictly more powerful, but it greatly increases the number of corner cases that need to be considered when writing correct handlers. Just as a small subset of the issues, consider some data structure for which a mutex must be held in order to correctly recover. Assuming the mutex isn't held at the time the handler is installed, you need to consider 3 cases: (1) the mutex isn't currently held (so the handler must acquire it and remember to release the mutex before resuming normal execution), (2) the mutex is held by some active call frame sitting between the thrower and the handler (in most cases, it would then be safe to modify the data structure, but the handler absolutely must not release the mutex), and (3) the mutex is held by another thread (it's probably not possible to recover in this case). Standard exception handling is non-local control flow, and that can make some situations difficult to reason about. Exception/condition handling where stack unwinding is optional is non-local control flow on steroids, engaged in 3D Chess Boxing.
- metroholografix 7y agoThat is true but I'd rather have the strategy in my toolbox and the choice to deploy it when needed rather than the language implementor making that decision for me. That's a fundamental difference between Common Lisp and other more popular languages. CL tries to give you all the tools and trusts you to use them responsibly. Other, more opinionated languages, limit the problem solving approaches they offer in the interest of (popularity|performance|implementation simplicity|personal philosophy). The CL philosophy makes a lot of sense if you examine its background and the culture that birthed it: a language designed to solve hard problems that did not have well-defined solutions.
- aidenn0 7y agoI think this particular one is fairly straightforward: 1. It's a non-obvious solution (Lisp had (and in some cases, still has) other methods of doing what other languages do with exceptions before the current system 2. It was hard to implement in popular languages; any language without closures is unlikely to have this. 3. More dynamic languages that could implement these fairly easily inherited their exception system from less dynamic languages, with some other features tacked-on, or got the dynamic features after the exception system was already created. 4. Situations in which you aren't going to restart are already (mostly?) solved by the "shove the call-stack into the exception object" which significantly reduces pain compared to e.g. C++ exceptions.
- avodonosov 7y agoRe 2: the condition system is easy to implement, try/catch implementation includes all needed building blocks.