research was supported by the BMFT under
Grant ITW 8902 C4.
- (Nested) function calls will be written
with (round) parentheses, while [embedded] structures or lists
will be distinguished by [square] brackets. Since in the above
eq definition signum can be seen as the constructor of
a structure, this version can be simulated in RELFUN, too.
Since RELFUN employs a LISP-like prefix notation also for
builtin relations such as < and >, the runnable
RELFUN forms of the two versions are
eq(signum[X],-1) :- <(X,0). signum(X) :- <(X,0) &-1.
eq(signum,0). signum(0) :- &0.
eq(signum[X],1) :- >(X,0). signum(X) :- >(X,0) &1.
- The syntax shown for full RELFUN will continue to
be PROLOG-like. In the implementation it becomes equivalent
LISP-like list expressions. Although the (older) LISP-like syntax
will not be shown in this paper, some users still prefer it to
the (newer) PROLOG-like syntax. RELFUN has been given two
syntaxes to facilitate communication between users from the
LISP and PROLOG communities.
- We do not make
use of the argument that is a mapping (or `functional' in, e.g., the relational database sense)
while its inverse is not (some small countries' areas
coincide if rounded to 1000 sq. mi.), because RELFUN does allow
non-deterministic functions, as will be shown shortly.
- Following LISP, RELFUN currently does
not distinguish arithmetic operators as infixes, but like all other
operators applies them as prefixes.
accesses a selected subset of COMMON LISP functions as builtins.
Unusually named examples
are the numeric successor and predecessor functions
1+ and 1-, whose application to an argument, say
6, in mathematical or PROLOG syntax becomes 1+(6)
and 1-(6), returning 7 and 5, respectively.
RELFUN's ecal primitive, a combination of LISP's eval
and PROLOG's metacall, permits the activation of structures,
as in ecal(1-[1-]), returning -2.
- RELFUN's once primitive (or ``!'' symbol) could
be employed above (or after) the is-call to prevent the
possibly diverging search for further solutions when the
first solution is found, thus simulating the
usual - unbounded - minimalization of unary functions
[for (1+N)-ary functions ``|'' can be used
to minimalize over the first argument, making mu[F] a
function structure, as shown in square brackets]:
mu(F) :- once(0 is F(naturals(0,V))) &V. (or mu(F) :- 0 is F(naturals(0,V)) ! &V.)
[mu[F](|Nargs) :- once(0 is F(naturals(0,V)|Nargs)) &V.]
- While the need
for non-ground terms is self-evident in relational programming
(ground relational programming isn't very useful),
they require some justification in functional programming.
The serialise example shows how non-ground terms can
be useful internally in a computation even if its external
input/output is ground terms. This is analogous to an internal use
of complex numbers in computing real results.
- RELFUN only permits a single cut per clause, so
premises to the left of ``!'' can be interpreted as
the arguments of an implicit once operator followed by a neck cut. Also, as a ``single-cut language'', it is akin to
a committed-choice language (CCL), obtainable by (1) restricting the
left-``!'' premises to `guards' and by (2) parallelizing clause
invocation. Like for PROLOG, a cut(-avoidance)
discussion will be necessary for relational/functional languages.
For example, wang's sole cut can be encapsulated into an
if...then...else... (as shown in parentheses), a valued version
of PROLOG's ...->...;..., but this entails an is-variable
to avoid recomputation of the entire work.
Although some relational/functional cuts may be justified by the determinism of many
functions, the question of better ways of determinism specification
remains. For instance, one could declare the work
procedure as deterministic
in one place instead of using a ``!'' in each of its clauses
(in the final clause, just for uniformity and CCL kinship).
Note, however, that RELFUN employs ``!'' as part of the
clause syntax, like CCLs use ``|'', not as an ``extra-logical goal''.
In work this syntax acts
like clause-oriented determinism annotations (for a non-neck cut
also specifying a clause's ``commit point''), from which
a declaration for the entire procedure could be extracted.
- We do not
try here to capture the LISP subset in RELFUN which is required for our implementation of
RELFUN in LISP; it would need some profane features for reading/printing etc.,
but could avoid the advanced features mentioned.
This would provide a `codefinition' of RELFUN and LISP,
like the one proposed for PROLOG and LISP in
Kenneth M. Kahn's ``Pure Prolog in Pure Lisp'' response
(Logic Programming Newsletter 5, Winter 83/84) to the
``Pure Lisp in Pure Prolog'' [PP82] paper. A direct definition
of RELFUN in RELFUN has been prepared by reducing it to
a meaning-preserving sublanguage (via flattening or relationalizing),
for which a PROLOG-like (vanilla) metainterpreter can be given.