4 ms·
For some time now, I’ve been thinking that it’d be funny to add a Lisp-style condition system to Go by abusing panic, defer & recover. I think that it’d be pos
by rauhl 8y ago
For some time now, I’ve been thinking that it’d be funny to add a Lisp-style condition system to Go by abusing panic, defer & recover. I think that it’d be possible (since Lisp’s conditions are really just built atop THROW & CATCH).
I don’t really think it’s a good idea: Go’s lack of macros imply rather a lot of anonymous functions to get it to work, which would imply loads of parentheses & curly brackets. Not to mention that the lack of first-class type literals would make actually using it close to insane. But it’d certainly be interesting. It’d definitely not be idiomatic Go. Still … interesting.
- masklinn 8y ago> For some time now, I’ve been thinking that it’d be funny to add a Lisp-style condition system to Go by abusing panic, defer & recover. I think that it’d be possible (since Lisp’s conditions are really just built atop THROW & CATCH). How would you resume execution at the panic point? A conditions system requires that you don't unwind, afaik Go's panic do in fact unwind.
- kazinator 8y agoLisp-style conditions are implementable even over C setjmp and longjmp style control. The non-unwinding part is done by searching the chain of frames and calling functions, without taking any non-local control transfer. The frame linkage is assisted by maintaining a global or thread-specific stack top variable. A frame is declared on the stack, then hooked into the list using the global variable. When a control transfer does take place, the value of that variable is properly maintained to discard the frames that are in functions being abandoned. Source: been there, implemented that. I'm not that familiar with go but from what I remember of the descriptions of panic/recover, something similar should be doable.
- rauhl 8y ago> How would you resume execution at the panic point? You invert it: rather than panicking, then continuing from the panic point if things recover, you proceed, only panicking to perform a transfer of control. Interestingly, this is what Lisp does: SIGNAL[0] (the most primitive function) just looks for applicable handlers and calls them from most- to least-recent; this means that if a handler transfers control (panics, in Go terms) then the condition has been handled; if not, SIGNAL just returns NIL; ERROR[1] does the same thing, but calls INVOKE-DEBUGGER if no handler transfers control; CERROR[2] is like ERROR, but it adds a CONTINUE restart, which just lets control resume. It’s possible to implement this same structure in Go: conditions.Signal() would search for applicable handlers and execute them in order; if control transfers then it’d never return; conditions.Error() would invoke one or more handlers, or the debugger, and would never return; conditions.ContinuableError() would invoke one or more handlers, or the debugger, but might return. The key is that it’s possible to execute a restart in the dynamic context of the signalling function (via use of Go’s context.Context), and only rewind the stack when you don’t need to go back down it. I think — I’ve not yet implemented it! 0: http://www.lispworks.com/documentation/lw71/CLHS/Body/f_signal.htm http://www.lispworks.com/documentation/lw71/CLHS/Body/f_sign... 1: http://www.lispworks.com/documentation/lw71/CLHS/Body/f_error.htm http://www.lispworks.com/documentation/lw71/CLHS/Body/f_erro... 2: http://www.lispworks.com/documentation/lw71/CLHS/Body/f_cerror.htm http://www.lispworks.com/documentation/lw71/CLHS/Body/f_cerr...
- masklinn 8y agoI see, you'd only be using panics for the unwinding handler, not for the actual conditions system.