Our primary motivation in developing DLP was to provide
an environment suited for implementing distributed knowledge
based systems,
such as expert systems and systems for distributed problem
solving.
It is widely recognized that, for modeling a domain of
expertise or problem solving, preference should be given
to a declarative language for knowledge representation.
Nevertheless, although we have clearly stated such
a preference by taking Horn clause logic as a base language
for DLP, it is our (strongly held) opinion that a mere
declarative language does not provide sufficient means to
control search and inference to the extent
necessary for building systems
with non-trivial functionality.
Partly, this control can be effected by relying on a standard way of
evaluation, such as the left-to-right evaluation
of Prolog goals,
or by defining a strategy adequate for the problem at hand
as described in [WO84].
A language such as Prolog, however,
allows more drastic means for effecting control,
notably by means of the assert and retract
statements, the use of which is justifiably frowned upon
by those taking a strictly declarative stand.
When thinking about parallelism the ideological gap
between a pragmatic approach and what is theoretically
justifiable seems to widen, inevitably.
Serious difficulty in exploiting the parallelism inherent
in the computation model of logic programming
languages has been caused by the need to restrict
the number of processes created for evaluating a goal,
and to avoid excessive communication between processes. Cf. [Co87].
Moreover, for reasons of synchronisation several ad hoc
solutions have been proposed,
such as the wait statement in Parlog, and the annotated variable
in CP. Cf. [Ra86].
Rather than adhering to some established conception of
concurrent logic programming (cf. [Ri88]), we have
decided to invest what, to our mind,
is needed for distributed problem solving,
and more specifically for distributed logic programming.
With respect to issues of knowledge representation
we have taken the stand, that although we wish to support
a declarative language, we also wish to provide
a programmer with sufficient means for programming
a fit solution, even if this would mean leaving
the declarative realm.
As a defence, for efficiently exploiting parallelism,
this seems unavoidable;
for knowledge representation, although not unavoidable,
providing non-declarative constructs inspired by the
paradigm of object oriented programming simply means following
a trend, that is giving in to the need expressed
by programmers in the field.
It has been argued that the introduction of object oriented constructs
removes one of the major weaknesses of logic programming: its lack of
structure.
The paradigm of object oriented programming,
indeed, has proven to be very useful as a guiding
principle for programming in the large.
Object oriented programming allows to shift the focus from
procedures that manipulate data
to the data that represent the problem at hand.
Data are encapsulated by objects, for which
an interface must be defined to
govern the communication with other objects.
The obvious advantage is a clear separation between
specification and implementation, which allows for
rapid prototyping and reusing code,
and moreover facilitates the maintainance and modification of a program.
Objects provide more protection than modules,
since the discipline of object oriented programming
enforces to specify how communication takes place between objects.
Another important contribution of object oriented programming
has been the use of inheritance, in defining objects that
are almost alike, or more generally speaking in specifying the
relations between objects.
Inheritance may occur in a number of guises.
Most simply, inheritance may be viewed as code sharing.
For the inheriting object, extra code must be specified
to effect that the object in some sense specializes
the inherited object.
In a typed setting we would be tempted to speak of
the inheriting object as belonging to
a subtype of the type of the inherited object.
However, in [Am89] it is adequately observed
that subtyping is a far more abstract notion,
that encompasses inheritance by code sharing.
Objects in DLP may inherit non-logical variables
from other objects as well as clauses, by code sharing.
A rather different form of inheritance, found for instance
in Actor languages [Ag86], is achieved by delegating
messages to the inherited objects,
whenever the inheriting object does not provide
any specific functionality for dealing with a method call.
Examples will show how inheritance by message delegation
may be programmed in DLP.
In a previous chapter it has been shown how to
extend Prolog with primitives for parallelism that
fit within the framework of object oriented programming.
Our main focus in this chapter will be on how to
combine object oriented constructs such as inheritance and method
delegation with logic programming.
Parallelism will only be of secondary interest.