|
|
"No single language can support every style, but a variety of styles
can be supported within the framework of a single language. Where this
can be done, significant benefits arise from sharing a common type
system, a common toolset, and so forth. These technical advantages
translate into important practical benefits such as enabling groups
with moderately differing needs to share a language rather than having
to apply a number of specialized languages." - Bjarne Stroustrup
There is no one-true programming methodology:
- Object Oriented programming groups data into classes and
operations on those classes. Conceptually, the "same"
operation might do different things, depending on the classes of the
data it is being applied to. Typically, classes can be defined in
terms of other classes (inheritance), so that the data within a
particular instance of a class, and the operations applicable to those
instances, can be shared between the new class and the class(es) from
which it inherits.
- Functional programming describes all computer operations as
mathematical functions on inputs. Typically, a function can be created and returned from other functions as first-class data. This function
object may then be passed as input to other functions, perhaps be
composed with other functions, and eventually, applied to inputs to
produced a value. Objects can be defined in terms of functions that
encapsulate certain data, and operations on objects can be defined by
functions encapsulating the objects. Purely functional languages do
not have assignment, as all side-effecting can be defined in terms of
functions that encapsulate the changed data.
- Procedural languages essentially perform everything as
side-effects to data structures. A purely procedural language would
have no functions, but might have "subroutines" of no
arguments that returned no values, and performed certain assignments
and other operations based on the data it found stored in the system.
Common Lisp provides integrated support for all these methodologies:
- There are procedural operations such as assignment and many
different kinds of iteration and other control flow constructs (even
go). Some functions come in two versions: one which
side-effects its inputs and one which does not.
- There is good support for functional programming. In fact,
much functional programming technology was first developed using
earlier Lisps. Anonymous functions can be
produced within other "function factories" and returned
as indefinite extent, first-class objects. In
particular, a function created in this way has access to the local
variables of the function in which it was defined - even if the new
function is used after the defining function has already returned.
This is what allows the encapsulation of data described earlier.
- Common Lisp, with the Common Lisp Object System (CLOS), was
the first object-oriented programming language to receive an ANSI standard. It is, arguably, the most
complete and advanced object system of any programming language. It
supports:
- multiple-inheritance, where classes can inherit from multiple
superclasses.
- multi-method dispatch, where operations can be specialized not
just on a single object, but on any of the arguments for the
operation, or any combination of those arguments.
- method combination, in which the means by which several
applicable operations to a particular set of arguments can be
combined, is itself an object-oriented specification, definable by the
programmer.
- operations that can specialize on particular instances of
classes, rather than on just the broad class of the arguments.
- shared class variables (slots, attributes) that are shared by
all instances of a class, in addition to instance variables which are
unique to each instance.
- specification of the creation operation for instances of a class
as an object-oriented program, definable by the programmer.
- The behavior of operations on objects (methods) are themselves
defined as first-class
objects, which can be specialized by the programmer.
- Access to classes themselves as first-class
objects. The objects which define the behavior of classes are
themselves classes, usable directly by the programmer.
These features, combined with the Metaobject
Protocol, make CLOS itself an object-oriented program which can be
customized extensively by the programmer.
The Common Lisp support for each of these programming methodologies is
generally more complete than languages specialized for just one of the
methodologies. What makes Common Lisp truly useful, however, is that
these different methodologies have been well integrated with each
other, and with other features of Common Lisp. For example:
- All operations in Lisp are invoked the same way, whether they
are side-effecting "procedures", normal functions, or
operations specialized on classes. No special syntax is used, and the
caller need not be aware of how the operation was defined. In fact,
the operation can even be redefined to work
differently, and the call will correctly use the new
definition. (Unless that is not desirable.)
- Instance (or shared class) variables of an object can be
accessed by class-specialized functions, and called the same way as
any other function.
- The same assignment operator can be used to assign values to
local or global variables, to instance (or shared class) variables of
an object, or to conceptual "places" that are represented by
functions that encapsulate the notion of "place".
- All operations in Lisp are first class objects and instances of
some sort of function class, regardless of whether they are
side-effecting "procedures", normal functions, or operations
specialized on classes. Each of these function objects can be passed
as arguments to other operations, and applied to arguments in the same
way.
- All data in Common Lisp is an instance of some
class and can participate in operation specialization (method
discrimination) - even functions, characters, and the components of
the object system itself.
- Run-time typing can be used for class
discrimination.
- Every operation in Lisp, whether a normal function, an
operation specialized on classes, or even a construction for procedural
control flow, always returns something. There are no such things as
"subroutines," which cannot be composed in expressions. Thus
operations can be combined in a functional way.
- All operations in Lisp can return multiple values. This
encourages functional programming, even within object-oriented
programming, by making it unnecessary to side-effect arguments merely
because an operation conceptually produces more than one value. The
multiple values are just returned. (There's no need for "output
arguments".)
- The dynamic nature of Lisp allows
functions, classes, and operations on classes to be redefined or added
to. If this results in new instance variables for instances of a class,
the new variables are added to old instances with appropriate (and
programmer controllable) initial values. If new class definitions or
operations on them make a different set of operations applicable to a
particular set of arguments in a call, the program which makes the
call will be updated automatically to use the new operations.
|