5 ms·
To see the REPL and debugger advantages of Common Lisp over other Lisps, Python, Haskell etc., you really should try for yourself in SLIME or SLY (a SLIME fork)
by Kessler83 5y ago
To see the REPL and debugger advantages of Common Lisp over other Lisps, Python, Haskell etc., you really should try for yourself in SLIME or SLY (a SLIME fork) imo.
But anyway, let's say I made an error somewhere and the program halts, putting me in the debugger. I can then examine each frame preceding the error. I can see every value going into my functions and jump around in the code generating those values. I change the code, while the debugger is still running, recompile it into the halted program and then pick a frame point right before the error occurred, to test if my changed code solves the problem. If it doesn't, I'll examine some more, perhaps start a second instance of the REPL to experiment a bit, then try another change in my code. All the while, I don't lose state. Once the problem is solved, my program will continue where it was as if the problem never happened.
For something like game programming, where you may be deep in the game and have encountered some rare combination of circumstances, this is simply invaluable.
- noisy_boy 5y agoHaving dealt with Angular dev server restarting for the tiniest code change, this sounds like a dream.
- dgan 5y agoHa! Very interesting, Thanks for feedback. The number of times I restarted a game after 1 line change + recompilation..
- jonathankoren 5y agoREPLs are great, and I always prefer a language with one than one that doesn’t, but being able to patch a running system is Lisp’s killer feature in my opinion. I’ve never seen another language that support that. I had a bug in a long running program that would only show up after like six hours. I couldn’t replicate it in isolation because it had something to do with how state was being maintained. I set a conditional breakpoint right before the crash, inspected the stack, patch the function, and then had it pick back up by reëvaluating the current function call. Damn thing just worked. It was amazing, and saved me so much time.
- bobnamob 5y agoThis is one of the fundamental features of the BEAM (the Erlang/Elixir virtual machine) as well.
- db65edfc7996 5y agoPython programmer not accustomed to a "real" REPL. My closest experience would be Jupyter notebooks, where dangling state is more a liability than an asset. > ...inspected the stack, patch the function, and then had it pick back up... After you edit the live state of the program, how do you translate that into code sitting in source control? Do you save this blob of memory and pass that down through generations?
- yellowapple 5y agoOne way would be to make the change in the source file and then recompile/reload that one function. This is pretty easy to do with SLIME; you can highlight the snippet of code you want to evaluate, and then send that to your program to be evaluated on-the-fly.
- jonathankoren 5y ago1. Stop the system. 2. Modify the source code containing the function. 2a. Save the file. 3. Copy function definition to the debugger’s repl, and evaluate it. 4. Resume the system from frame that calls the function. But yes, you must be diligent about making sure the source files contain the code that is actually running, but that’s not much different than artifact tracking.
- lispm 5y agoUsually one wants to make the change persistent in the sources. Step a): One just evaluates from the sources, while changing them. Once done -> save sources. Step b): Create a patch file, which changes the image. Such a patch file can be loaded while starting an image, until one decides to save a new image with the changes already loaded. For example there is a new release for the commercial LispWorks IDE once every one or two years. Users usually get only patch files for bug fixes during the one or two years maintenance. Thus I have a directory for patches to LispWorks, which are loaded when I start the base image.
- the-alchemist 5y agoYou can actually do something similar (much more limited, it sounds like) on Java, of all things. https://devblogs.microsoft.com/java/hot-code-replacement-for-java-comes-to-visual-studio-code/ https://devblogs.microsoft.com/java/hot-code-replacement-for... As long as it doesn't change the class signature, you can happily edit-save-replace code, and it jumps to the top of the method you're editing. It's basically instant, so you don't suffer the javac and JVM startup cost. I don't think I can do the same in more dynamic languages, like Ruby or Python. Or, maybe, my IDEs don't support it (IntelliJ suite).
- twobitshifter 5y agoThat’s really cool to see. For Ruby, pry is usually the REPL to use for hot reloads. https://www.cbui.dev/an-introduction-to-pry-a-ruby-repl/ https://www.cbui.dev/an-introduction-to-pry-a-ruby-repl/
- westoncb 5y agoI hear this talked about quite a bit, but it still doesn't quite make sense to me why it's such a big deal: I know this situation where debugging-fix attempt loop is far more efficient if you don't lose state, but it's nowhere near a pervasive situation: when it comes up, I can generally write something quickly to re-create the necessary parts of the state automatically. If I was doing that every day, or even every week, I could see it being a huge advantage to incorporate a solution in the language—but at least for me it just doesn't appear to be an obstacle that often (incidentally my background was initially in game programming, too).
- edgyquant 5y agoI wonder what it is that prevents e.g. python from having a similar “persistent state in development” tool/repl? I’ve never really used lisp other than a MAL I did a few years ago for kicks so I’m not well versed in its dev tooling.
- twobitshifter 5y agohttps://www.libhunt.com/posts/72311-reloadr-hot-code-reloading-tool-for-python https://www.libhunt.com/posts/72311-reloadr-hot-code-reloadi...
- Y_Y 5y agoYou can definitely do something similar with e.g. ipdb from ipdb import launch_ipdb_on_exception with launch_ipdb_on_exception(): foo()
- jedimastert 5y ago> I can generally write something quickly to re-create the necessary parts of the state automatically. I think this is where the trip up is. In a game, for example, that state is often exceptionally complex and getting everything right back to where you came from is usually only possible running the full game and recreating the same state.
- westoncb 5y ago