可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I've been getting more into Lisp and Lispy languages lately, and I'm finding them quite powerful.
One thing I've been reading all over the net is that a benefit of writing in Lisp, Clojure, etc, is that you can edit your program "while it's running".
Perhaps I'm missing something, but what is the point?
Sure, it might save a few seconds, but is that all? Whenever I make a change to my program I just stop it then start it again, and that has been working fine for decades.
There must be a reason other than just saving time -- what is it?
Can someone give me a good case study that will make me drool over this feature? :)
Looking forward to drooling!
回答1:
There are some extremely cool use cases. One example is in GUI programming - I saw this while developing a GUI app in real time as it was running beside my Emacs: I added code for a new button and hit "C-c C-c" to compile that single function, and the button just appeared in the window! Didn't have to close and reopen the app. Then I began tweaking widgets and manipulating the layout, and the open window would instantly rearrange itself - buttons would move around, new text fields would just pop into being, etc. as soon as I executed each little change I'd made.
Another example is an excellent screencast about the Clojure OpenGL library "Penumbra" where the programmer creates a 3D tetris game in real time. He starts with an empty OpenGL window next to his emacs. He defines a cube object - C-M-x - and it's on the screen. Runs a command to rotate it, immediately it starts spinning. Runs a loop defining 5 more cubes in different locations, pop-pop-pop-pop-pop they appear. It's all immediately responsive, the full OpenGL toolkit right there to play with. Add a new surface texture to your cube and see it appear right away. It becomes a malleable 3d world - the code dynamically modifies the existing world instead of closing and reopening the 3d canvas with every change.
Penumbra Livecoding Screencast - download HD version for best experience.
There is also a great presentation/screencast about the audio library "Overtone" for Clojure. The library is a synthesizer toolkit where you have a set of synth functions to manipulate the soundwave. During the presentation, the developer writes a bit of code that starts a tone playing. He then spends ten seconds writing a loop that plays that sound 10 times but makes the frequency higher each time, and again C-M-x and you hear it, notes ascending higher. Over the space of 20 minutes in real time he gets a song going. It looks like a ton of fun.
Overtone Presentation Link
Other uses would be, for example: Web crawling/data mining - develop and refine algorithms for extracting information in real time, seeing the data returned at each step; Robotics programming - send commands to a robot while it's live; Facial/image recognition - with a library like OpenCV watch your changes instantly update what the library recognizes in an image/video as you're developing the code; Mathematics work (Clojure has "Incanter" for statistics); and any environment where you want to immediately see what effect your changes have had on the data you're working with.
So that's the most fun aspect of having a REPL in front of you. Things that weren't tangible, malleable, interactive, start to be. GUI design, 3D graphics, programmatic sound production, extracting and transforming data, these things normally have been done at arm's length. But with Clojure (and to some extent with other dynamic languages too) it's made to be really tangible and immediate; you see each change as soon as you write the code, and if something doesn't work or you don't get back the result you expected, you just change what you missed and re-execute it immediately.
Clojure is very aligned towards doing this. The wild thing is you can use Java libraries in real-time the same way - despite the fact that Java itself can't! So Overtone is using a Java synth library in realtime despite the fact you never could in Java, Penumbra is using the Java OpenGL bindings, etc. This is because Rich Hickey designed Clojure so it could compile to JVM bytecode on the fly. It's an amazing language - Clojure has made a huge contribution to how incredibly fun and productive programming can be.
回答2:
There must be a reason other than just saving time -- what is it?
No, there isn't. I mean, there never is: the whole reason to use a computer at all is to save time. There's nothing a computer can do that you can't do by hand. It just takes a little longer.
In this case, I wouldn't dismiss "a few seconds", given that it's one of the things I do more often than anything else, all day long, for my entire programming career. A few seconds to recompile, a few seconds to re-run, several seconds to recreate the state my program had the previous time -- even on a fast workstation, it can easily be a minute between iterations. (It used to be much worse, but faster hardware has only made it less-awful, not good. Whole-file-or-worse recompiles are I/O-bound, and may never* match the speed of more granular compilation.)
In Lisp, recompiling a single function in an already-running process is almost instantaneous (I've never seen it even 0.1 sec, even on my 5-year-old laptop), and restarts mean I don't have to recreate my state, even when something signals.
Here's a tool that gives me over a 100x speedup of one of the slowest and most common things I do as a programmer. I don't know what else you'd need. We can probably make up some reasons, but if this isn't reason enough I don't know what would be. Um, it's also pretty cool? :-)
(* Whenever somebody says "never" about something involving technology, that person invariably ends up looking like a complete moron 2 years later, and despite Lisp's longevity, I am sure to be no exception.)
回答3:
There is a marketing slogan for Lisp:
With Lisp, and its incremental development method, the cost for a change to a software system depends on the size of the change, and not the size of the whole software.
Even if we have a large software system, the cost (time, ...) for a change stays in relation to the size of a change. If we add a new method or change a new method, the effort remains in relation to the effort to edit the method, incrementally compile the the method and incrementally load the method.
In many traditional software environments, the change of a method may need a partial recompilation, a new linked executable, a restart, a reload, etc.. The larger the software is, the longer it takes.
For a human this means, we get possibly out of a state of flow. That's part of the productivity of good Lisp environments: one can make a lot of changes to a software system in a short time, once the programmer feels comfortable and enters this state of flow. I guess many have experienced this, where work gets done in a short time - opposed to times when one sits in front of a system which is unresponsive and we are faced with wait times.
Also there is little cognitive distance between us and the program we are working on.
For example if you edit a class in a batch environment, you have to imagine the effect the changes have. In Lisp you edit a class and change at the same time the objects themselves. That means you change the behavior of objects directly - and not a new version of them after a batch edit-compile-link-run-test cycle.
In a Lisp system, you change a class in a CAD system and then it can be immediately active.
When people ask, if Lisp works for large software teams, the answer may be that the large software team is not necessary, if you work incrementally. The problem then was/is that really good skilled software developers familiar with incremental development were (are?) rare.
In many applications there is a separate scripting language layer, sometimes for the original developers (and not for users). In Lisp this is not necessary, Lisp is its own extension language.
回答4:
In the real world this is mainly used in development and like many features its only worth drooling over in the right context.
- personal programmer enlightenment bliss*
- true continuous deployment.
- zero planned downtime Service Level Agreements.
- debug production servers.
*not a guarantee.
for me, and i suspect some others here the real benefit of this
REPL driven development is that it can be
indescribably fun. addictive even. It can sometimes really give a sense of crafting-code. give it a try... come on man try it out, first REPL's always free :)
one big draw these days is
continual deployment.
currently the idea for continual deployment is that you change one thing, build everything (or package it rather) then deploy. with the lisp model its actually possible to edit a deployed (usually a box that is recieving a mirror of real customer sessions) box while it is in deployment.
just a pedantic note. you dont actually edit running classes. you compile a new copy of the class and leave it in a known location (a var) then the next time it is used the new copy is found and used. its not really editing while running and more like new code takes effect immediately this reduces the scope of the devlopment process from programs to expressions (typically functions).
another drooling point is the idea of getting the bennefit of
security fixes with out having to declare any downtime. you can do an upgrade with out it costing your SLA any of you precious "scheduled downtime". If you have to schedule planned downtime six months in advance, and you only get two hours of it then (for these poor souls) it could really make them drool.
If you have repl access to your running application as it is deployed (potentially (with permission) at a customer site) you can connect to the app while it is running and run tests on the existing code
in the existing context with out having to stop and connect a debugger. you also wont get any speed loss from a debugger. It's possible to do this with out a REPL, though when you get the repl in there you can then create new code easily (some will say that injecting dynamic class loaders through the debugger is easy) and then fix things. So you could connect to a running server. discover that a function failed to re-connect to a database after a short outage and then reconnect it right then and there.
as with all programming constructs there
never will be a silver bullet and this continual deployment/development has an interesting downside: you program can be correct in memory and wrong on the disk. if you compile a function then break it and save then the only working copy of the code is the one running. I't useful to be aware of this and re-eval files just after you save them.
This may sound fanciful so go checkout how to Embed a Clojure REPL in your production application
回答5:
I remember somebody from NASA described his experience. His team implemented the soft used in a spaceship back in the 70s. And they effectively modified their soft remotely on the fly when some bugs were found.
Or imagine you have a long process taking days to execute and at the end it cannot write results because of permissions or other small problem.
Yet another example. You are in the integration phase and you have to make a lot of small changes. And again a lot of them. I dream about such a possibility in Java because currently it takes me 30-40 min to rebuild and reinstall my application (to rebuild it again in 10 min).
回答6:
If you look at something like Erlang, the point is to avoid down time.
It runs on stuff like phone switches that you can't just turn off for a few seconds.
For more normal uses, though, it's a "nice to have" feature, but yeah, probably not critical.
回答7:
You see real data. That is a big advantage. You then don't have to speculate.
回答8:
Because you can?
Seriously, just try it out for while, and you will feel the pain when you come back to your old programming language without REPL.
Instant feedback, easy making quick tests without having to set-up a fake program state in your test fixture, Ability to inspect state of running program (what is the value of that variable). All of these are a real time savers.
回答9:
It's mostly for development, where it's just a time saver.
But time savers are staggeringly important.
Once you're used to it going back to the old way feels like going from flying to swimming in tar.
回答10:
In industrial systems this is used for PLC programming to alleviate downtime and unsafe conditions.
These are systems that are used on nuclear power plants, manufacturing systems, steel mills, etc. The process is always running, continuously, and down time is very expensive or unsafe. Imagine a system that is controlling the cooling of a nuclear reactor, you cannot turn that system off to deploy new code, you must be able to modify it as it is running.
This is similar to the Erlang answer for phone switch systems.
回答11:
Well, imagine you need to patch a server and not stop it.
If you do this in a "typical" language, that's going to involve some heavy magic. You have to grub around 'behind' the executing code. I think it'd require patching the function tables and so forth, all in assembly and manipulating the pointers to functions. A good place for bugs.
In Lisp, the idea of updating without downtime is built into the language model. While there are some update complexities you can't get away from (how do you handle a long-running connection), it doesn't require the heavy magic of a compiled language.
Although I haven't spent significant time on it (ie anything useful), I did work out a prototype of a server in Common Lisp that would do at least some live patching over a network without downtime.
回答12:
Another good thing apart from modifying the program on the fly without having to restart everything (having done it for decades doesn't mean it is the best thing, right?), is that you get to inspect your program in its current state and being able to figure out what's going on.
回答13:
Casey Muratori just did a few lessons on how to do this with C and Microsoft's C/C++ compiler. It's actually pretty simple, just a few dozen lines of code. Check out videos 22/24/25:
https://www.youtube.com/watch?v=WMSBRk5WG58
In game design, the rationale is to be able to more quickly tune constants to find the emotional tenor you are aiming for. Things like game feel, non-player behavior scripts and setpiece lighting/ambience benefit a lot from this.