10 ms·
Restarts in Common Lisp
- slifin 7y agoKeep meaning to look at this, Clojure has some libraries for this I could use: https://github.com/clojureman/special#alternative-libraries https://github.com/clojureman/special#alternative-libraries
- nabla9 7y agoThe condition system in Common Lisp is really amazing piece of work. Error and exception handling is just subclass of larger set of possible uses called conditions.
- olah_1 7y agoHey Sulami, this is off topic, but how did you get those nice sidebar footnotes? What theme are you using? Or how did you edit the css?
- dtoma 7y agoIt looks like https://edwardtufte.github.io/tufte-css/ https://edwardtufte.github.io/tufte-css/
- sulami 7y agoThis is the tufte-css, with some modifications. Raw css is here: https://github.com/edwardtufte/tufte-css https://github.com/edwardtufte/tufte-css My additions on top (and all other source) here: https://github.com/sulami/sulami.github.io/tree/develop/css https://github.com/sulami/sulami.github.io/tree/develop/css
- metroholografix 7y agoI find that Practical Common Lisp has not aged well. Maybe it's the "practical" part with the specific examples the author used -that are now terribly dated- that is mainly responsible, but the end result is that I no longer recommend it. My goto recommendation for newcomers is Norvig's PAIP which is full of insightful moments and unbelievably good code and for people with more experience "Let over Lambda" by Doug Hoyte, which is a mind-blowing book mainly because of the time-transcendent nature of the examples Doug chose.
- sulami 7y agoI'm planning to read PAIP over the upcoming weekend as a follow-up, I've already got it sitting here. I know next to nothing about AI, beyond the basics of RNNs, so I'm hoping to learn a lot.
- kannmig 7y agoThe material handled in PAIP mostly focuses on classical symbolic AI, as opposed to the modern ML-based AI that you refer to in RNNs. (Not to discourage you from reading the book, of course!)
- weavie 7y agoYou may need more than a weekend!
- billsix 7y agohttps://norvig.com/21-days.html https://norvig.com/21-days.html
- yarrel 7y agoIt's AI in the rule-based GOFAI paradigm rather than modern neural-network-based ML. Treat it as a review of some of the historical classics of computer science and you can't go wrong.
- vz8 7y agoFor those not in the know, PAIP is Paradigms of Artificial Intelligence Programming, with a fantastic repo here: https://github.com/norvig/paip-lisp https://github.com/norvig/paip-lisp
- nabla9 7y agoPAIP is a great book. It both teachers Lisp programming and "classical" AI programming. Knowing classical AI IMHO should be considered as part of programmers toolbox. What was once bleeding edge AI is now high level heuristic problem solving.
- 7y ago
- aidenn0 7y agoAside from restarts, the core difference between the Common Lisp condition system and exceptions in most other languages is that the exception handler can run before the stack is unwound. Having the call-stack available at the time the handler runs can be very useful; many modern dynamic languages will save some of that information in the exception object. It's still surprising to me that so very few languages have copied this feature (or even independently discovered it).
- HerrMonnezza 7y agoI think you meant to say that the "condition handler can run before the stack is unwound." (whereas exception handlers in Java, C++, Python unwind the stack while searching for the handler) (I agree it's a nitpick, but since your comment is likely directed to people who do not know the condition system, it's better to be precise.)
- madmulita 7y agoOh, that's why they need to unwind the stack!? These things are what some take for granted and others don't even know how to ask. Thanks.
- KMag 7y agoUnwinding the stack isn't necessary to find the exception handler. The language runtime code that finds the correct exception handler could just as easily walk the return pointers stored on the stack without modifying the stack pointer, frame pointer, or current return pointer. The reasons for unwinding the stack are (1) avoiding running out of stack space, particularly if the exception handler might itself throw (2) simplifying/optimizing the very common case of wanting the exception handler to unwind the stack. It's vastly simpler in languages where you have resources that must be freed in the correct order (C++ destructors, Java monitors being released, etc.) to ensure correctness. It's difficult to correctly reason about mutating sate to recover from an error while other pieces of code might actually be holding the mutexes/monitors keeping that data safe. It's an optimization, because you already have to do much of the work of stack unwinding (in the absence of destructors, monitor releasing, and the like) in order to find the correct exception handler.
- jgrant27 7y agohttps://imagine27.com/error-handling-or-the-emporors-old-clothes https://imagine27.com/error-handling-or-the-emporors-old-clo...
- artemonster 7y agoCan somebody please also elaborate what is the difference between condition system in CL and "new thing" algebraic effect handlers? On the surface I see no difference, other that the latter is being a more formalized version of conditions? But we have same properties: 1. signal a condition to some handler(s), possibly with value. 2. reify the stack into a (delimited up to level with handler) continuation and let handler decide what to do with it: save, restart, resume with some value. Am I missing something?
- dfox 7y agoThe CL condition system is completely orthogonal to any concept of continuations or stack unwinding. Both condition handlers and restarts are plain functions and any kind of stack unwinding has to be implemented inside these functions (by means of TAGBODY/GO, BLOCK/RETURN-FROM or THROW/CATCH).
- hencq 7y agoTo add to that, as an example, here's how you could implement something similar in Clojure [1]. It just relies on dynamic scope to run the handler without unwinding the stack. [1] https://gist.github.com/msgodf/6f4e43c112b8e89eee3d https://gist.github.com/msgodf/6f4e43c112b8e89eee3d
- lilactown 7y agowhat's the difference from what you said (handlers and restarts are functions) vs. a continuation, which could ostensibly just be a function that has closed over the state of the runtime before the condition was triggered?
- lilactown 7y agoAFAICT Algebraic Effects are a way of encoding conditions into a static type system. The idea of signaling a condition and passing a continuation is not the new part (as you've noted), it's the _algebra_ part, where a type system can check at compile time that these conditions that a piece of code calls are implemented by the context it is called in.
- phoe-krk 7y agoNitpick: > While Common Lisp calls them “conditions”, I will stick with “error” in this post, because I don’t think “condition” is very self-explanatory if you’re not familiar with the language already. Please forgive my inaccuracy. This is misleading. It is possible to signal conditions that are not errors, and therefore do not require stack unwinding, like errors do. The condition facility allows one to execute arbitrary code with arbitrary arguments at the SIGNAL site. `SIGNAL` walks the list of condition handlers and executes the type-matching ones in order of their binding. If a handler returns normally, then next ones are executed; if all matching handlers are exhausted, `SIGNAL` returns, and code execution continues. CL-USER> (handler-bind ((condition (lambda (c) (format t ";; Foo: ~A~%" c))) (condition (lambda (c) (format t ";; Bar: ~A~%" c))) (condition (lambda (c) (format t ";; Baz: ~A~%" c)))) (signal 'condition) 42) ;; Foo: Condition CONDITION was signalled. ;; Bar: Condition CONDITION was signalled. ;; Baz: Condition CONDITION was signalled. 42 Of course, a handler can perform a non-local transfer of control elsewhere, e.g. by using `GO` or `THROW`. In such a case, control is transferred out of `SIGNAL`, so next handlers are - naturally - not invoked. While I understand that this post is trying to appeal to language newcomers, simplifying the whole condition system to an "error try-catch" is a drastic misrepresentation of the condition system that will leave the newbies with the impression that that's all that is possible with that feature. Since it seems that the author is a Lisp newcomer as well (which I wholeheartedly admire! :), I'd advise him to use the original notation of "condition", instead for the one of "error".
- kqr 7y agoThis is a central point in this context, far from mere nitpicking.
- phoe-krk 7y agoUpdate: some of my fixes have made it into that article. Thanks, sulami, for the IRC discussion!
- michaelfeathers 7y agoCorrect me if I'm wrong but can't all of the cases covered by conditions be handled in an OO language by providing an object that one can register conditions with and call signals upon? I'm trying to imagine library support for languages that don't support conditions directly.
- shadowgovt 7y agoInteresting. This looks like an implementation of the abstract computer science notion of continuations (https://en.wikipedia.org/wiki/Continuation); https://en.wikipedia.org/wiki/Continuation); neat to see them used this way.
- ska 7y agoIt's really orthogonal to continuations. Scheme has them (continuations) explicitly. CL chose not to, I think for performance reasons if I recall correctly.
- phoe-krk 7y agoThe Common Lisp condition system is actually just a dynamically-scoped hook system. Handlers are the actual hooks; conditions are the object that may trigger some of the hooks when they are signaled. Restarts are an addition on top of the hooks that allows for easier non-local transfer of control; they provide little that handlers do not provide unless you count the Lisp debugger - by design, the only way to leave the debugger is by using a restart. In other words: no continuations here.
- shadowgovt 7y agoInteresting. I'm not sure I understand; what do the dynamically-scoped hooks lack that continuations would give you?
- phoe-krk 7y agoTo be frank, I do not know. I am not a continuation specialist or even an adept, so I cannot say myself; all I can say for sure is that a condition system can be implemented (and is actually implemented in practice) without any continuations, and therefore doesn't require the underlying language to support continuations. (Common Lisp, for example, purposefully doesn't have them in standard - see http://www.nhplace.com/kent/PFAQ/unwind-protect-vs-continuations-original.html. http://www.nhplace.com/kent/PFAQ/unwind-protect-vs-continuat...)
- sedachv 7y ago
- mrow84 7y agoA long time ago I wrote a conditions system for python: https://code.google.com/archive/p/pyconditions/ https://code.google.com/archive/p/pyconditions/ I wouldn't recommend using it, but it is an interesting error/control model, and I always wondered why it hasn't seen wider implementation - I presume because it is closer to the "dangerous" end of the power spectrum.
- kazinator 7y agoIn TXR Lisp, I unified condidtions and restarts into one thing: exceptions. By programmer convention only, restarts are exceptions derived from restart. The documentation has dialect notes about this with a comparative example: https://www.nongnu.org/txr/txr-manpage.html#N-00F77525 https://www.nongnu.org/txr/txr-manpage.html#N-00F77525
- kazinator 7y agoThe author doesn't seem to understand that not all exceptional situations are errors, which suggests he is a complete newbie to exception handling, which explains why he didn't propose the word "exception" instead of "condition".
- metroholografix 7y agoNot all conditions signify exceptional situations. The author conflated error with condition but you're doing the opposite of conflating condition with exception. The big plus of the Common Lisp condition system is that it gives you a programmable substrate that you can use to implement a wide variety of signaling and control flow systems. It does give you error and exception handling -on top of the condition system- but that shouldn't shoehorn your thinking into just these problem domains.
- Jtsummers 7y agoAs an example of non-exceptional condition signaling: http://jacek.zlydach.pl/blog/2019-07-24-algebraic-effects-you-can-touch-this.html http://jacek.zlydach.pl/blog/2019-07-24-algebraic-effects-yo... Progress can be signaled, and then dealt with if needed. In headless mode it won't be handled. In a console it could be a progress bar or statement. In a GUI, update a variable that changes the status display. And it ends up as little more than a no-op if there are no handlers for it. Nothing exceptional about it, but creates a great deal of flexibility in managing a system.
- deleted 7y ago[deleted]
- kazinator 7y agoThere is also nothing conditional about reporting progress, except in the sense that the progress is an indication of state. According to a Honeywell PL/I reference manual, "a condition is a state of the executing program". The progress of some activity being 50% through is a state of the executing program. (All the built-in PL/I conditions are exceptional situations though. This is really the same use of the word "condition" that we find in "condition status register", a machine word that tells us via flags that exceptional situations have happened like numeric overflow.)
- nickpsecurity 7y agoWith a quick DuckDuckGo-ing, I found this intro to be really understandable compared to most links I read: https://z0ltan.wordpress.com/2016/08/06/conditions-and-restarts-in-common-lisp/ https://z0ltan.wordpress.com/2016/08/06/conditions-and-resta...
- chaitanya 7y agoMany years ago I wrote about restarts in CL using the example of a CSV parser: https://lisper.in/restarts https://lisper.in/restarts Fun fact: the restarts based CSV parser was based on some real world work me and a colleague had done for an online travel portal. I wrote about it here: https://www.reddit.com/r/lisp/comments/7k85sf/a_tutorial_on_conditions_and_restarts/drceozm/ https://www.reddit.com/r/lisp/comments/7k85sf/a_tutorial_on_...
- nerdponx 7y agoR, continuing its theme of being a weird Lisp with C syntax and really bad function names, has a condition system: https://adv-r.hadley.nz/conditions.html https://adv-r.hadley.nz/conditions.html