|
|
To say that a language is dynamic may mean different things:
- That the language is exciting to work with.
- That the types of data can be examined
and checked at run-time.
- That the behavior of functions and other operations can be
changed (or created) at run-time.
Here we mean the last of these. In particular, the behavior of a Lisp
program can be modified while the program is running without
necessarilly having access to the original source code, and in any
case without having access to or knowledge of those parts of the
application which are uneffected by the change. The changes to the
program may be made interactively by a programmer or by the program
itself.
There are several ways in which this comes about:
- Function are first-class. A
"function factory" can be constructed which returns
function objects as values. If the "function factory" is
compiled, these function objects are compiled, too. These programs
can then be explicitly called on arguments. Thus a program can
produce the functions it needs at run time, making different
functions for different situations.
- The global definition of a named function can be changed at
run-time, simply by creating one of these function objects and
storing it in the symbol that represents the name of the function.
By default, the compiler must arrange for callers of a global
function to access the object stored in the symbol naming the
function. There are various optimizations permitted where this is
not done, however. Some implementations provide for both the direct
call optimizations and the redefinition of global
functions.
- The function
LOAD can
be called by any Lisp
program. If the file being loaded contains new definitions, these
are added and made available to the application that called
LOAD. If the file being loaded contains new definitions
of existing functions, classes, etc., these definitions
replace the existing definitions in the manner
described above. The Common Lisp Object System allows classes to be
redefined in running programs, and the system will automatically
update existing instances of the changed class to conform to the new
definition. The programmer has control over how this updating is
performed. In addition, the function COMPILE-FILE can be
called by any Lisp program, including one which just created the Lisp
source file to be compiled. The result can then be loaded with
LOAD.
- The function
EVAL can be called by any Lisp
program. This evaluates a list
representation of a program. There are many Lisp utilities for
examining and creating list data. These can be used to construct
programs on-the-fly which are then evaluated. In addition, the
function COMPILE can be called by any Lisp program to
create compiled-functions directly from list data representations of
programs. These techniques make it easy to write Computer Aided
Software Engineering (CASE) and other software development systems in
Common Lisp.
Using a dynamic language provides several benefits:
- Programs can be developed and delivered more easily.
- It is not necessary to define all parts of an application
before testing or even delivering part of it. The combination of the
Lisp top-level and the function
LOAD do not use a traditional static program linker, so
one can start the program running without having to track down all
undefined references. If the missing parts are never used, there
will never be a problem.
- When there is a problem, only the broken part need be
redefined. This can be done while the application is still running.
There is no need to laboriously stop the application, recompile
everything, restart the application, and recreate the error state
before proceding with testing.
- Mission-critical applications can be maintined more easily.
- Bug fixes or new functionality can be installed without stopping the
application.
- Only the bug fix or new functionality need be distributed
and loaded. For large applications distributed over modem or other
networks, this can be a major consideration.
- The programs themselves can be simpler, more robust and easier
to develop and maintain. This comes partly from:
- The ability to have functions create other first-class
functions on the fly. See Object-Oriented and
Procedural Lisp.
- The fact that Lisp comes with the functions
LOAD, READ and EVAL which
make it easy for anyone to create initilization or customization
files that set global variables, etc. There is no need for an
application developer to write such functions, they are already
there.
- The well-defined, object-oriented way in which programmers
can define how data reconforms itself to changed class definitions
makes such code quite clean.
- These features can be exposed, at the programmer's discretion,
to general users of an application for the purpose of customization.
There is no need to define and develop a "customization" or
"user macro" language as Lisp itself has everything needed.
All of this is independent of the environment in which the application
is to be run. For example, even in a Lisp implementation that
supports the creation of stand-alone applications which run outside
the Lisp top-level, that application can still
be defined to provide the user with a command that calls the function
LOAD (perhaps after first confirming a manager's
password).
A key commonality to the above benefits is that the cost of making
a change to a dynamic system is proportional to the size of the
change, whereas the cost of making the same change in a static
system is generally proportional to the size of the system.
As the size of systems or the expected numbers of changes grow, it
becomes increasingly important to support more aspects of the system
dynamically.
|