Read again what he writes: 'everything ... is automatically included - there is nothing that is not included'.
LispWorks comes a huge image that contains all the necessary features, from graphics, networking, memory management, ...
Actually you have to REMOVE things to make it smaller (for example using a so-called tree-shaker during 'delivery').
In Java you need to tell which classes/etc. to use. In LispWorks you just call the functions are instantiate the classes - every language feature/library. that he needed for his application, is already included.
In LispWorks you start the image and type to the listener. For his task all the functionality was available then.
So Lisp's great advantage over Java is that you don't have to put "import ..." at the top of the file? Clearly it's more fundamental than that. Trying to eke out minor victories over other languages on every front just trivializes the areas where Lisp truly dominates.
Put such a Lisp image that includes all the tools and classes on an embedded device. Then connect of the network and develop/debug the functionality incrementally while it runs.
In Java, oh wait, I forgot class XYZ, lets push it onto the device and see if it loads. Maybe not, it needs some more class files, ... then the Java capabilities for runtime changes are kind of limited - well, you can hack the class loader.
One area where Lisp has been used a lot, is interactive development using so-called images. During development one works with 'images' that contain all the necessary software - that's a part of the 'ball of mud' approach (Smalltalk environments like Squeak work similar and have extensive tools to control that). LispWorks also allows to save preconfigured images - with LispWorks 6 one can dump running programs (with GUI) and restart them later.
Back when I was writing a lot of Common Lisp (CMUCL), the image system didn't seem like a win over files, but a misfeature necessitated by the bug of taking 20 seconds to start a program. Images are inherently messy; after you've changed a running system two or three times, it's even odds whether it will actually be the same as a system started from scratch with ostensibly the same variables and functions, in my experience, and there's no good way to be certain, besides restarting. Since you're going to have files of source code anyway, using runtime images just creates the opportunity for your two official copies to get out of sync. This isn't worth the few times you could hotfix something instead of restarting the system.
Does not sound like development in Lisp (or Smalltalk). You were using Lisp as a batch language - there are possibly better languages for that.
I tend to run my Lisp images for days, weeks, months. As long as possible. Restarting is always an unwelcome interruption of my flow. Working with files is no problem. I have the code in the LispWorks editor in buffers/files and compile incremental from there. Sometimes I recompile a whole buffer and sometimes only parts. A good Lisp environment will also keep track of changed code and have a command to compile only those. Alternatively I compile a buffer and then walk through the compiler warnings fixing the code until the warnings are gone - never leaving the image.
walk through the compiler warnings fixing the code until the warnings are gone - never leaving the image.
To me, this seems like a disaster waiting to happen if you're doing something complex. When there are bugs in my code, it usually means bad things are happening to my data, my data structures, and the state of my program in general. When I find the bug, it often seems far easier to fix the bug and start over than it would be to both fix the bug and track down all the consequences and fix those as well, perhaps writing some more code to help with that which might end up with bugs in it... my attention stack was never that large to begin with, and as it gets smaller I try harder and harder to avoid situations where I recursively just have to do this one more thing before I can do the thing I want to do.
I did run some of my images for weeks, and one webapp in particular for months. After the first few days, though, I was always apprehensive about making changes to it, since I couldn't be sure my files were in sync with what was in the running system -- what if I'd forgotten to write a change to a file -- and since my system was running, I couldn't just reload from the file to make sure, since if there was a difference I'd lose the working copy in favor of one I'd replaced. It was all very nerve-wracking. In contrast, the systems I had that were written in Python could be changed and then bounced, trading about 5 seconds for all that stress[1], and the systems I had that were written in PHP didn't even need that; changing the file on disk was enough.
[1] I do know that I could have done this with CMUCL, but I assumed that there would eventually be a point at which I realized it was all worth it...
It might be surprising, but people have been writing large and complex software systems with this approach. Several hundred thousand lines of Lisp code in some apps were definitely reached by several Lisp applications.
Oh, I'm quite aware of it! I'm not saying that image-based development is unworkable; I'm saying that developing in a monolithic image seems more difficult to me than systems made up of many smaller pieces (files, in this case).
Nor am I knocking lisp. I think there are a lot of great things in various lisps: though I have specific nits to pick with each lisp I've actually used, some of the problems I encountered were due to attempting to solve problems I would have just lived with in other languages. I've said elsewhere that I think one of the reasons lisp languishes is that it's seductively powerful -- why spend time learning someone else's library when you can write the part you need in less time?
I agree with one of the g'parents, though, that lisps' strengths are in the macros and code-is-data areas, and passing over that in favor of things that most every competing language has in this era (built-in datatypes, nice IDEs, REPLs) seems severely underpromising.
You don't have to convince me that incremental development at the REPL is a good thing. But what you're talking about is package management, and Java is perfectly capable of creating an uberjar that contains all dependencies. Even if LispWorks does it better, we're talking about differences in convenience rather than differences in capabilities.
Lisp is adequate in many ways, and excellent in others. But a lot of descriptions of why it's excellent focus on what appear to be trivialities. Maybe there's some sort of gestalt at work here, where the sum of these minor differences is greater than its parts, but if that's the case you're doing a really poor job describing it.
LispWorks comes with the full thing, including graphics and IDE by default. You put it on the machine, run it and it comes with everything INCLUDING the incremental compiler.
Zero assembly needed.
Java is usually developed in a batch fashion with lots of files, classes/modules, jars, ... it needs an IDE like Eclipse that keeps track of all the components, has a build process, assemble the components, load it into some virtual machine, connect the external debugger, etc. etc.
Lisp applications (here with LispWorks) are often developed with a single image and incremental modification.
This not a small thing. This is a huge difference in convenience. Something that seems to be important for HIM (and me).
This incremental development capability is one reason I prefer to use Lisp. For me a piece of software is not a bunch of files that are on the disk, compiled and linked and then started. MY mental model which I like best is to see an application as a sea of running objects which are communicating (the part of dead code on the disk is only necessary to jump start and assemble these objects). Once the program is running in some primitive fashion, I tend to prefer to think about modifying the running objects by a bunch of changes (the changes tend to be in files, sometimes code, sometimes data - often code that more looks like executable data). Not everybody uses the same mental models when developing and I am spoiled by interactive systems like the Lisp Machine (which Jack also knows), where the philosophy is very similar: http://lispm.dyndns.org/genera-concepts/genera.html
The lisp/smalltalk way: have all my tools within arms reach so I don't have to reach for anything while I'm developing. When I'm finished press a button to get everything I didn't end up using in the end put away.
Everyone else: have a very small set of tools so that I must constantly go back to the tool shed and pick up something I now need, often forgetting to put back things I'm not using anymore.
The second case is overstated in the case of at least MS Visual studio with Resharper, which will automatically suggest use statements when you use a class that isn't visible, and tell you about any includes that aren't being used. But with Lisp/Smalltalk (provided they have "tree shakers") you don't have to think about this, the computer will just do it automatically.
Often a Lisp program at runtime consist of a 'runtime environment' (memory management, ...) and the data in the heap: functions and all kinds of Lisp objects (characters, lists, hash tables, CLOS objects, ...). An 'image' is a saved dump of this memory.
Typically you can start Lisp and just reload the memory from the heap dump (the image) on disk and do some automatic re-initialisations (for example reopen windows, reconnect to files and databases, restart processes, ...). All the code and data will be restored. You are back, where you saved the image before.
Imagine you would dump the memory of your JVM to disk and restart it later.
The Lisp vendor will provide you with an 'image' that contains the base language, some extensions, graphics, networking, editor, debugger, inspector, gui designer, etc.. You can then write a program, load all the program files, load all the data and configuration files and save an image. When you restart the image later, all your application code and data is back. This can save a lot of time during development.
Interesting. Sounds like you run, step into, and then modify this big blob of binary data (from the inside!) until you've shaped it into what you want. Weird. :)
In both Lisp and Smalltalk you (can in Lisp, must in Smalltalk) develop from an "Image" based point of view instead of a file based one.
The simplest way to understand this is to realize that you are basically living "inside" the running exe that you're writing.
Contrast this with e.g. C++ where you write a bunch of files, fight with the compiler until they turn into some black box exe, then run said exe and try to guess what it's doing based on the blueprints of your source file. To actually see what's happening inside the exe you would have to run some kind of debugger, but you can't take action based on what you see. You're looking through a glass.
Not so with Lisp/Smalltalk. If you see something wrong you can just fix it on the spot and continue running.
> The simplest way to understand this is to realize that you are basically living "inside" the running exe that you're writing.
Ah. Given what I already know, it sounds a lot like opening up a Python REPL, importing all the code you need, and then starting the main loop of the program.
> You're looking through a glass.
Heh, through debugger-colored glasses. :)
I see what you mean though. With C++, if you find your problem, you stop the whole show, go back to your source, take a stab at a fix, recompile, and then run once again in the debugger. With Lisp, you're just there the whole time.
Exactly. And as a consequence of this both Lisp and Smalltalk allow you to restart from exceptions. Lisp has an extremely sophisticated method (most powerful of any language imo) called "restarts". These make it a lot easier to build much more robust software than it is without them. http://www.gigamonkeys.com/book/beyond-exception-handling-co...
LispWorks comes a huge image that contains all the necessary features, from graphics, networking, memory management, ... Actually you have to REMOVE things to make it smaller (for example using a so-called tree-shaker during 'delivery'). In Java you need to tell which classes/etc. to use. In LispWorks you just call the functions are instantiate the classes - every language feature/library. that he needed for his application, is already included.
In LispWorks you start the image and type to the listener. For his task all the functionality was available then.