Java may or may not enable fast development, but the reasons actually given for why Lisp development is fast certainly apply equally to Java.
Java may or may not enable fast development, but the reasons actually given for why Lisp development is fast certainly apply equally to Java.
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.
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.
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
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.
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...
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.
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.
> In LispWorks you start the image and type to the listener.
I'm very new to Lisp (but not C, C++, Java, Python, and some other similar languages). Can you please tell me what an "image" is?
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.
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.
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.