4 ms·
The gains from Lisp-like support of live-environment programming are not small, but they are hard to communicate succinctly. The costs are real, but not onerous
by mikelevins 9y ago
The gains from Lisp-like support of live-environment programming are not small, but they are hard to communicate succinctly. The costs are real, but not onerous for a language designed to support such features.
But a person designing and implementing programming-language tools has to deliberately choose to provide the needed features because implementing them after the fact raises the costs and lowers the benefits. That means such a person must believe that the gains are worth the cost. The only people likely to believe that are people already familiar with those kinds of systems.
- auganov 9y agoOn a fundamental level, there's not much difference between Lisps and any other language with real runtime eval. It's just that, say, in your average JS project you're going to have a lot of state all over the place, state that depends on side effects. I don't think Lisps do much to solve that. Clojure helps by discouraging state and side-effects, namespaces let you have everything sort of be a global in a manageable way. I actually like to use the 'repl' module in nodejs. With a little bit of effort, you can make the dev experience much easier.
- lonjil 9y agoIt's not just about having eval(), it's also about having tooling to exploit its capabilities. I'm currently learning OpenGL with CL, and if I make a change to my main loop, I just hit a few buttons to recompile it without interrupting anything. As soon as it's finished compiling my loop silently switches over to it and the output reflects the new version of the loop. I have a Discord bot written in CL. If I want to add a new command or feature, I write it, hit a few buttons, and it seamlessly integrates with my bot without interrupting anything it's doing. If I have a problem with a macro, I can hit a button to have it expand right there in my code, and when I see the problem I hit a button to unexpand it. The editor will even catch errors and ask what you want to do, without interfering with other threads, which has been very useful while developing my bot.
- mikelevins 9y agoThe great Lisp and Smalltalk systems are designed from the ground up with the assumption that a programmer may at any point inspect and possibly change absolutely anything in the dynamic environment of the running program. Everything is designed to facilitate doing that with the reasonable expectation that the program will continue to work correctly. Such systems are designed for writing software by modifying a program while it runs. That basic assumption is a giant knife-switch that pervasively affects everything in the language and environment. Consider, for example, the generic functions CHANGE-CLASS and UPDATE-INSTANCE-FOR-CHANGED-CLASS. Those functions are in the Common Lisp language standard. That makes no sense unless the standard assumes that a Common Lisp system can modify a program while it runs. Only a minority of programmers want such systems, but to be fair, only a minority of programmers have worked with them enough to understand them. Not everyone prefers that style of programming, but most programmers will probably never have the opportunity to find out whether they prefer it. I did have the opportunity, and I learned that I did prefer it. I still prefer it thirty years later. Get back to me with a Clojure or JS environment that does what I miss from a great Lisp or Smalltalk environment. Let me trigger an error and walk the call stack to inspect parameters and intermediate results. Give me a keystroke to get a list of every other piece of code that calls the function with the error--don't make me wait more than about a second for the list. Let me interactively edit the values on the stack in the suspended computation or, better yet, change their types (and have them properly reinitialized), then resume the computation. Let me redefine a function that's on the call stack and then restart the call using the new definition. Let me serialize the entire dynamic state of the program to disk, copy it to a colleague's machine, and start it up to show my colleague the same error in the same dynamic environment. Let me do all of that interactively without needing to leave the original break loop triggered by the original error. Oh, and package the tools as a single modest-sized executable that I can run with a simple command line or a double-click, that launches in a couple seconds or less. I don't know of such a Clojure or JS environment. If you do, I would be grateful to learn of it.
- mikelevins 9y agoSorry to reply to myself, but when I awoke this morning, it occurred to me that above I am describing my daily-driver programming environment from early 1988, Coral Common Lisp (except that who-calls wasn't built in; it was a contrib). Besides the previously-mentioned features, I could build a windowing UI by dragging pieces together. I could build the resulting native-code app for delivery by choosing "Save" from a menu. I could write WDEFs (the code resources that defined window shape and behavior) and other low-level stuff interactively in Lisp. I could patch arbitrary calls with assembly code written and debugged interactively in the Lisp environment (one of the SK8 authors was previously an assembly-language video-game programmer; he was ecstatic about this feature of CCL). Comparing my current daily-driver development machine to the one on which I was using Coral Common Lisp in 1988, the new machine has twice the word size, 400 times the clock speed, 16,000 times as much RAM, and 400,000 times as much disk space. Meanwhile, the development tools are in many ways worse, rather than better.