[HN Gopher] Debugging Lisp: fix and resume a program from any po...
       ___________________________________________________________________
        
       Debugging Lisp: fix and resume a program from any point in stack
        
       Author : todsacerdoti
       Score  : 58 points
       Date   : 2022-12-06 14:54 UTC (8 hours ago)
        
 (HTM) web link (lisp-journey.gitlab.io)
 (TXT) w3m dump (lisp-journey.gitlab.io)
        
       | vindarel wrote:
       | Hi everyone, happy to share more about my Common Lisp journey if
       | you have any question.
        
       | TacticalCoder wrote:
       | People using Emacs without _paredit_ or _lispy_ to automatically
       | close parentheses  / do semi-structural editing _should be put in
       | jail!_ ; )
        
       | Labo333 wrote:
       | I'm wondering whether it would be possible to build some debugger
       | for Python to fix that!
       | 
       | For example, I modified my IPython config to always activate
       | https://ipython.org/ipython-doc/3/config/extensions/autorelo...
       | 
       | It works well for modules with redefined functions. So if you do
       | from module import f1, f2                  ans1 = f1()
       | ans2 = f2(ans1)
       | 
       | and f2 fails, then you can just modify the code of module and
       | relaunch `ans2 = f2(ans1)`.
       | 
       | What is not available is reloading classes, for example if it
       | looks like:                   from module import Class
       | c = Class()         c.f1()         c.f2()
       | 
       | and there is a bug in f2, then the class won't be redefined.
       | 
       | I guess there is no perfect way to do it (for example what if f2
       | needs some variables defined in Class.__init__), but the
       | situation is the same for Lisp with its dynamic typing.
       | 
       | So maybe the situation would be to have some command like
       | `%reload Class`.
       | 
       | The other obstacle is restarting from a frame, and I understand
       | that Python's standard exception handling doesn't allow that. But
       | pdb exists so there should be a solution.
        
         | sidmitra wrote:
         | Some of the basic hot-loading features can probably be
         | approximated in Python. Here's some from my bookmarks(i've not
         | tried them personally)
         | 
         | - https://github.com/breuleux/jurigged
         | 
         | - https://github.com/reloadware/reloadium
         | 
         | I would imagine lisp can do this on a whole different level.
         | Emacs seems like a testament to that. Basically the entire
         | editor feels like eval()
        
           | gjvc wrote:
           | jurigged is excellent.
        
         | gumby wrote:
         | Lisp has a lot of capabilities here that Python doesn't. It has
         | restartable exceptions, the ability to redefine functions and
         | whole classes at runtime, the ability to write new functions
         | (/variables/classes etc) in the process of those redefinitions.
         | Its debuggers are written in Lisp (completely extensible by you
         | at runtime) offering a REPL right at the debug site.
         | 
         | Python is a completely different beast.
        
         | Jtsummers wrote:
         | > the situation is the same for Lisp with its dynamic typing
         | 
         | Common Lisp and Smalltalk (quintessential dynamic systems) both
         | track the existing instances of a class. If you update the
         | class definition then they can update the existing instances of
         | the class. In CL you'd want to specialize `update-instance-for-
         | redefined-class` to handle the update.
         | 
         | http://clhs.lisp.se/Body/f_upda_1.htm#update-instance-for-re...
        
           | thelopa wrote:
           | Most CL implementations don't "track" the instances so much
           | as have them point at a proxy for the real class object. When
           | redefining a class, the old proxy object is marked as stale
           | and then updated to point at the new class. This allows the
           | runtime to lazily update instances to the new class (using
           | the method you linked to) as they are encountered. As a
           | result, you can have instances from several different class
           | generations kicking around in memory.
        
         | mrweasel wrote:
         | I suppose you could create a new class, with any fixes and wrap
         | the existing object in the new class. It will kinda work, due
         | to the duck typing, but it's not that elegant.
         | 
         | For the restarting, yeah, I don't know either.
        
           | henrydark wrote:
           | in ipython just running %debug will get you in pdb in the
           | particular frame that threw, there you can modify stuff using
           | normal python, and then you can tell pdb to continue
        
         | jorams wrote:
         | > I guess there is no perfect way to do it (for example what if
         | f2 needs some variables defined in Class.__init__), but the
         | situation is the same for Lisp with its dynamic typing.
         | 
         | CL has the generic function update-instance-for-redefined-
         | class[1] for this, so you can customize what happens to
         | instances when a class gets redefined. I think most developers
         | don't actually define methods for it all that often, but it's
         | there if the defaults don't work for you.
         | 
         | [1]:
         | http://www.lispworks.com/documentation/HyperSpec/Body/f_upda...
        
         | stonemetal12 wrote:
         | PDB has the interact command that drops you into a full blown
         | python repl at the debug point. Changing an existing method on
         | a class isn't a big deal. Redefining a class is possible as
         | well but updating existing instances to the new class requires
         | metaprogramming tomfoolery.
        
       | artemonster wrote:
       | IMHO, if CL got their handler system a tad tiny step further and
       | better, they would have landed in a full algebraic effect
       | territory, with a total flexibility of resuming your ,,throwers"
       | and not only restarting them. Paired with unparalleled CLOS
       | capabilities that still drives context oriented programming,
       | aspects, subjective dispatch research, CL would have been a
       | religion by now.
        
         | fiddlerwoaroof wrote:
         | I don't quite understand what you mean by the distinction
         | between resume and restart here. CL condition handlers allow
         | code that signals a condition (sort of equivalent to "throws an
         | exception) to continue on as if the condition was never
         | signaled. You just need a handler-bind somewhere in the stack
         | that doesn't perform an exit. You can use this to do things
         | like catch a type error and convert the input value to the
         | expected type on the fly.
        
       | moonchild wrote:
       | You can do the same thing in j, using the 'cut back' debugger
       | command. It is a useful and powerful facility indeed.
        
       ___________________________________________________________________
       (page generated 2022-12-06 23:01 UTC)