6 ms·
I find it funny and also ironic that a lot of modern languages re-discover Lisp's amazing features decades later. The other day I was infuriated to see my Pytho
by behnamoh 2y ago
I find it funny and also ironic that a lot of modern languages re-discover Lisp's amazing features decades later. The other day I was infuriated to see my Python program halt after 9 hours of API calling to my own home server. The API calls were similar (calling an LLM with a pre-defined prompt template, constrained using grammars). I wanted to save the state of the program and exit it before running the remaining iterations separately. So I needed a way to modify the current running Python code and inspect the variables. I couldn't figure out a way to "dig into" the running Python process and save the state and/or fix it. So I lost 9 hours worth of work.
A couple days later, I saw this:
https://malisper.me/debugging-lisp-part-1-recompilation/ https://malisper.me/debugging-lisp-part-1-recompilation/
The fact that CL had this feature built into the language decades ago just blows my mind. Not to mention numerous other features (like the most powerful macro system there is), etc.
- pyuser583 2y agoWas there no exception being thrown?
- kqr 2y agoI don't know how that would have helped. Most languages (including Python, AFAIK) unwind the stack when an exception is thrown, all the way up to the nearest catch. Whatever you wanted to do at the place of throwage is no longer possible because that stack doesn't exist other than as an incomplete printout. In contrast, Common Lisps condition system keeps all stack between throw and catch so you can resume from anywhere in between, possibly with altered code or local variables. Basically, Common Lisps exception stack traces are interactive by default.
- ptsneves 2y agoIronically that stack unwinding is exactly why I like a straight old sigsegv. Just dump the core and analyse the frozen state. One thing that annoyed me in go is that even when it core dumps on panic and after I worked on the backtrace analyser for gdb, most of the core dumps were useless as everything of worth was already unwound and lost.
- mananaysiempre 2y agoHidden in plain sight is the fact is that structured exception handling in 32-bit Windows (the linked-list-on-the-stack version[1,2], not saying anything about the gigantic-tables “zero-cost” version) is a resumable exception system a la Common Lisp conditions—inevitably, seeing as it subsumes SIGSEGV coredumps! [1] http://bytepointer.com/resources/pietrek_crash_course_depths_of_win32_seh.htm http://bytepointer.com/resources/pietrek_crash_course_depths... [2] http://bytepointer.com/resources/pietrek_vectored_exception_handling.htm http://bytepointer.com/resources/pietrek_vectored_exception_...
- aidos 2y agoI don’t quite understand what sort of state the system is in at this stage. So the process has errored but not exited? I know that during the exception you can pry into the variables from the stack. When do they get cleaned up? https://stackoverflow.com/a/5328139/171450 https://stackoverflow.com/a/5328139/171450
- behnamoh 2y agoFor that to happen, you must have implemented what that SO answer says in your code. In contrast, CL allows you to modify the current running code and apply fixes.
- aidos 2y agoI guess I’m confused about what running code even means after the exception. The process has crashed. Is it waiting to be reaped by a parent process?
- lispm 2y agoIf there is an exception a matching error handler will be selected and called in the context of the error. A default handler could be a debugger, a break loop (which is a Lisp REPL), something which asks the user waht to do or it could be a handler provided by the software, which could do anything, including looking for restarts and using one. For example the variable a is unbound and we try to add 3. CL-USER 37 > (+ 3 a) CL shows an UNBOUND-VARIABLE error and provides Restarts. Restart 3 is a USE-VALUE restart. Error: The variable A is unbound. 1 (continue) Try evaluating A again. 2 Return the value of :A instead. 3 Specify a value to use this time instead of evaluating A. 4 Specify a value to set A to. 5 (abort) Return to top loop level 0. Type :b for backtrace or :c <option number> to proceed. Type :bug-form "<subject>" for a bug report template or :? for other options. We are now in a break loop, a REPL one level deeper, in the context of the error. Let's see what the condition (-> exception) is: CL-USER 38 : 1 > :cc #<UNBOUND-VARIABLE 8010002EC3> we call one restart (listed above, number 3) interactively, it uses the new value and continues to compute the expression. It asks for a value. I enter 5 -> 5 + 3 = 8 CL-USER 39 : 1 > :c 3 Enter a form to be evaluated: 5 8 We can do it also programmatically. HANDLER-BIND establishes a handler for UNBOUND-VARIABLE. It invokes the restart USE-VALUE with 4 -> 3 + 4 = 7 CL-USER 40 > (handler-bind ((unbound-variable #'(lambda (c) (invoke-restart 'use-value 4)))) (+ 3 a)) 7 All this is the default behavior. There is no special "debug mode", attaching a debugger or "instrumentation of code" needed.
- kortex 2y ago> Most languages (including Python, AFAIK) unwind the stack when an exception is thrown, all the way up to the nearest catch. You might have to use a few tricks/hacks, but I'm pretty sure you can set up python in a way to breakpoint at an exception, including all local state at the throw site. Otherwise pdb would not work.
- pyuser583 2y agoDefinitely. It’s very possible to pause (pdb-like) or persist the local state/stack. But there needs to be an actual exception. If someone pulls the power cord, you’re out of luck.
- deleted 2y ago[deleted]
- eikenberry 2y ago> I find it funny and also ironic that a lot of modern languages re-discover Lisp's amazing features decades later. This is never surprising as Lispy languages are some of the most flexible and expressive languages. But that's the problem, it is too expressive. The Lisps always reminded me of mixed media (visual) art, where the freedom of expression from the mixed media sounds good on the face of it but in the end it generally produces sub-par works compared to more traditional single media art. It turns out that the restrictions of the medium are just as important as the expressiveness.
- sweeter 2y agothats a great analogy.
- eikenberry 2y agoThanks!
- cess11 2y agoI've seen shitty code running in 'prod' at every employment I've had as a developer. The language isn't that important, the people and the organisation are.
- eikenberry 2y agoIt's not important from an external standpoint, looking at code quality. Like in all the arts, most of it will be bad. That is not the point. The point is from the developers perspective as a medium. To put it another way, you can produce bad art in any medium but some mediums seem more conducive to creating good art.
- cess11 2y agoMaybe. You probably don't want to base your web development studio on colorForth for quite a few reasons but I'm not so sure artistic reasons are relatively important. You seem to think that organisational factors, like management, profitability, market influences and whatnot are less important than the conduciveness of the tooling to create good art. Why is this?
- albertzeyer 2y agoPy-spy or Pystack to inspect the state to certain degree. Or https://github.com/malor/cpython-lldb https://github.com/malor/cpython-lldb. Or more here: https://github.com/albertz/pydbattach/ https://github.com/albertz/pydbattach/
- mixmastamyk 2y agoIf you have a process running for multiple hours, it should be saving work to disk and be ready to pick up where it left off.
- fermigier 2y agoIndeed. Using Joblib for instance (https://joblib.readthedocs.io/ https://joblib.readthedocs.io/).