Earlier quoted context omitted.
That depends. Several mildly large programs have been written in Lisp. There should be code bases for applications reaching or surpassing ten million lines of Lisp code. There also should be code bases with relatively complex code, which have been maintained for more than a decade. For example the Cyc system is under continuous development since the mid 80s. A dialect like Common Lisp was designed such that applicati…
>A dialect like Common Lisp was designed such that applications in the large are possible. Interesting. Can you mention some of the Lisp language or other features that help with that?
* namespaces for symbols, in earlier days Lisp had a flat namespace
* compilation of files, means in a large system you can use 'ahead of time' compilation, where the compiler might give a lot of diagnostic messages. There is very little penalty to that, basically one can compile always and interactively.
* type declarations/hints which can be used for optimization, type checks -> see SBCL and CMUCL, and documentation
* lots of declaration forms which can be checked at compile time or runtime
* macros which can be expanded at compile-time. This can create early warnings/errors.
* function arglists, where the usage can be checked at compile-time (missing arguments, added arguments, ...)
* keyword arguments, which makes code more readable
* a very elaborate error handling system, which can not only catch errors, but which can be used to interactively or automatically repair some errors. Thus you don't get 'program crashed', but a handler gets called in the error context, which than can use provided explicit restarts. Errors types can be organized in an ontology with inheritance.
* runtime assertions and type checks work with the error system
* documentation features included: many declarations allow documentation strings
* robust runtimes which by default prevent corrupting the running Lisp as much as possible. Some earlier Lisps created unsafe compiled code. By default I would expect a Common Lisp system to detect all kinds of wrong access to data structures at runtime.
* optimizations, which can be restricted to certain code blocks
Plus
* an object system which can be used to provide extensible software, typically used to structure larger software. Also provides multi-methods which prevent being called with arguments of wrong types at runtime. Multiple inheritance. This allows a lot explicit structure in larger applications, which also can explored by reflection and which can be tailored for specific needs.
* features like macros and reader macros can increase the code density in larger software -> fewer lines of code and domain level code. By default Common Lisp favors larger identifies, but in larger codebases macros can significantly reduce code size and make external tools like preprocessors obsolete.
A different development methodology:
In static languages you tend to statically compile a program, build it, start it, test it. May be in some debug mode or with some kind of extension language interface.
In Common Lisp one may develop with a build while it is running and then make sure that these builds can be reproduced by compiling/loading the whole thing. This can reduce the typical development cycle time drastically. But different development models are possible: fully batch, pre-compiled + interactive, fully interactive.