[HN Gopher] Condition Handling in the Lisp Language Family (2001)
       ___________________________________________________________________
        
       Condition Handling in the Lisp Language Family (2001)
        
       Author : Jtsummers
       Score  : 36 points
       Date   : 2021-11-22 17:30 UTC (5 hours ago)
        
 (HTM) web link (www.nhplace.com)
 (TXT) w3m dump (www.nhplace.com)
        
       | smegsicle wrote:
       | > The establishment of protocols is a sort of before-the-fact
       | hedge against the "prisoner's dilemma"; that is, it creates an
       | obvious way for two people who are not directly communicating to
       | structure independently developed code so that it works in a
       | manner that remains coherent when such code is later combined.
       | 
       | Sounds very cool, and the article seems to edify wrt
       | functionality and abstract benefit, but how does it really help?
       | See: the more-or-less complete abandonment of resumable
       | conditions in other languages.
       | 
       | The practical differences between conditions and c++-style
       | exceptions seem to be:
       | 
       | 1. The stack is followed back, looking for a handler, rather than
       | being destructively unwound- 'restarts' don't necessarily 'try
       | again', they can continue from where the condition was thrown.
       | 
       | 2. While unhandled (ERROR) 'fatal conditions' land in the
       | debugger, nonfatal (SIGNAL)s imply that a sensible default has
       | already been provided, and, relying on point 1, continue
       | otherwise unfettered.
       | 
       | I remain curious about the kinds of practical architectural
       | impact this functionality provides- how often does everyday lisp
       | code signal nonfatal conditions? The hyperspec mentions that
       | *break-on-signals* can be used for visibility there...
        
         | jcynix wrote:
         | > I remain curious about the kinds of practical architectural
         | impact this functionality provides- how often does everyday
         | lisp code signal nonfatal conditions?
         | 
         | From my time programming on Lisp machines (long time ago), I
         | fondly remember wrapper functions (i.e. some macro wrapped
         | around your own code) like "with-open-file" which would open a
         | file and set up proper condition handling to close it on exit,
         | regardless of what happened inside... you could always be sure
         | that the file was closed when control left the wrapper, either
         | normally or abnormally. And if you where creating a file and
         | some exception occurred, the file would be removed and the file
         | system left unaltered (as much as possible).
        
         | kmill wrote:
         | I think an approximation to this in C++ would be to have some
         | thread-local objects called condition handlers that you set
         | using some RAII construct (so, something that will replace the
         | current condition handler and then later restore it when you
         | leave the current scope), and then when some function
         | experiences an exceptional circumstance, it calls some methods
         | on the appropriate condition handler object. The condition
         | handler is free to throw an exception itself if it wants to
         | destructively unwind the stack, but it can also do other
         | things.
         | 
         | It's through these condition handler objects that the caller
         | can bidirectionally communicate with callees before they
         | return.
         | 
         | In other words, it's like the visitor pattern, but rather than
         | passing the visitor directly you do so through a thread-local
         | variable, and also these visitors are designed to be
         | composable.
         | 
         | A more modern version of this, straight from the ivory tower,
         | are effects handlers, which I expect we'll see in more
         | languages as time goes on. The cool thing about effects
         | handlers is that they make it easier to reason about all these
         | nonlocal effects due to some well-thought-out restrictions.
         | They also have some good compositionality properties, and they
         | appear to be able to be compiled down to code that doesn't need
         | special runtime support (beyond what functional programming
         | languages already provide). The example I'm somewhat familiar
         | with is Koka: https://koka-
         | lang.github.io/koka/doc/book.html#sec-handlers
        
         | jbjohns wrote:
         | It's actually quite a good design idea because it is often the
         | case that lower level code knows everything that can go wrong
         | but has no idea what to do about it. Higher level code has this
         | knowledge. For an example, I remember reading a C library for
         | handling some common encoding. It simply swallowed format
         | errors because it didn't want to fail the whole function for
         | them and didn't have a way to communicate anything was wrong.
         | In a conditional system this could have been a condition and
         | the default function could be set up to ignore it, for example.
        
         | brandmeyer wrote:
         | IME, exception-handling works well as an error-handling
         | mechanism where a very simple policy is being applied for a
         | very wide range of error cases. Example: 0.0001% of the total
         | data in this analysis pipeline is malformed for reasons a-z and
         | A-K (and counting). Don't care; throw out that one datum and
         | continue.
         | 
         | Some web request went badly. We're concerned about leaking
         | internal details to the caller. So, you reply with a generic
         | error code, log something about it for operator investigation,
         | and make sure that any other state changes were rolled back
         | along the way.
         | 
         | Condition systems invert that relationship. Its not just a
         | failure to open a file, but a failure to open one specific file
         | for a specific use case in the pipline out of several that are
         | needed in total. In a condition system, the caller needs to set
         | up a handler for each one of those use cases, and possibly bind
         | some additional discriminating information to the arguments to
         | disambiguate them on the way back up the stack.
         | 
         | If a reasonable fallback policy is available, I'd much rather
         | partition the pipeline up such that the fallbacks are applied
         | on a case-by-case basis in the control flow of the caller.
         | Idiomatic Python code does this all the time with exceptions.
         | Idiomatic code with Optional types does so, too. Both methods
         | are well-suited to the task, and I have never found myself
         | wishing for a condition system when using them.
        
       | agumonkey wrote:
       | Talking about that, I found ~old (relatively) slides from phoe
       | (author of a CL condition system book) about control flow:
       | 
       | https://phoe.github.io/slides/control-flow.pdf
       | 
       | enjoy
        
       | throwawaybutwhy wrote:
       | (2001)
        
         | Jtsummers wrote:
         | Thanks, added. I'm usually good about adding the date.
        
         | smegsicle wrote:
         | Aha, so a relatively recent article!
        
       ___________________________________________________________________
       (page generated 2021-11-22 23:01 UTC)