In this first step, all deeply deterministic functional predicates
are transformed into functional RELFUN specifications. For our example,
this results in:
1+) fac(X1, X2) :- X2 is fac/2-1(X1). 1a) fac/2-1(0) :- !& 1. 1b) fac/2-1(X) :- X1 is -(X, 1), FX1 is fac/2-1(X1), Y is *(X, FX1) & Y. 2+) f(X1, X2) :- X2 is f/2-1(X1). 2a) f/2-1(s[X, Y]) :- A is -(B, A), s[A, B] is s[X, Y], A is fac/2-1(X), B is fac/2-1(Y) ! & u[s[X, Y], s[A, B]]. 2b) f/2-1(X) :-& [X, X].
The rules 1+ and 2+ are needed in order to allow to call the binary fac and f predicates from the toplevel. The original predicates are transformed into unary function definitions, renaming them by adding the suffix /2-1.
In general, this suffix has the
form /-
where
is the original arity and
is the
number of output arguments (specified by
in the mode
declaration). For
, the output values are embedded in a
values structure, e.g.
f(X,Y,A,B) :- A is +(X,Y), B is *(X,Y).
with the modes f(,
,
,
)
is transformed into
f(X,Y,A,B) :- values[A,B] is f/4-2(X,Y).
f/4-2(X,Y) :- A is +(X,Y), B is *(X,Y) &values[A,B].
This also works for non-adjacent output arguments: g(X,A,Y,B) :-
with modes g(,
,
,
) is transformed
into g/4-2(X,Y) :- &values[A,B].
Such value structures can be viewed as representing multiple-valued
functions as described in [\protect\citeauthoryearStein and Sintek1991].