% A BRIEF INTRODUCTION TO BASIC RELFUN, USING ITS PROLOG-LIKE SYNTAX % Harold Boley Feb 1992 (rev.: July 1996) % In RELFUN, a LISP list (e1 ... eN) or PROLOG list [e1,...,eN] is equivalent % to an (N-)tup(le) structure tup[e1,...,eN]. Logical variables are marked by % a caps- or "_"-initial. The PROLOG list pattern [1,2|V] shortens tup[1,2|V], % matching instances like tup[1,2,3,4,5] with the binding V = tup[3,4,5]. % A PROLOG clause c(...) :- b1(...), .., bM(...). in RELFUN becomes a kind of % 'hornish' clause, except that structures, incl. tup-lists, use brackets, not % parentheses. A conditional equation g(...) = f(...) if b1(...), .., bM(...) % in RELFUN is generalized to g(...) :- b1(...), .., bM(...) & f(...)., an "&" % (or 'footed') clause, whose "b" premises may accumulate partial results and % whose "f" premise returns possibly (non-)ground/(non-)deterministic values. % As in LISP, nestings like +(*(3,3),1-(8)) => 16 are reduced call-by-value. % "Passive" structures like +[*[3,3],1-[8]], using brackets, return themselves. % RELFUN's tup FUNCTION returns the tup STRUCTURE of its evaluated arguments: % tup(|R) :- & tup[|R]. % R will be bound to the tup of all arguments. % This permits calls like T is 3 & tup(*[T,T],1-(8)) => tup[*[3,3],7]. % The below definitions of append and naive reverse illustrate our RELational/ % FUNctional merger (e.g., "is" can invert functions almost as if relations). % PROLOGish REL style (inversion revrel(U,tup(1,2)) loops on MORE): apprel([],L,L). apprel([H|R],M,[H|S]) :- apprel(R,M,S). revrel([],[]). revrel([H|R],L) :- revrel(R,M), apprel(M,[H],L). % LISP-like FUN style (is-syntax tup[1,2] is revfun[U] exhibits inversion): appfun([],L) :- & L. appfun([H|R],L) :- & tup(H|appfun(R,L)). %NESTED (user) form -> % appfun([H|R],L) :- _1 is appfun(R,L) & tup(H|_1). %FLATTENED revfun([]) :- & []. revfun([H|R]) :- & appfun(revfun(R),[H]). %nest and (compiler) % revfun([H|R]) :- _1 is revfun(R) & appfun(_1,[H]). %flatten % Using nested or flattened clauses, the RELFUN interpreter allows this dialog: % rfi-p> apprel(tup(1,2),tup(a),U) % rfi-p> appfun(tup(1,2),tup(a)) % true % [1,2,a] % U = [1,2,a] % % rfi-p> apprel(I,J,[1,2,a]) % rfi-p> [1,2,a] is appfun(I,J) % true % [1,2,a] % I = [] % I = [] % J = [1,2,a] % J = [1,2,a] % rfi-p> more % 4th MORE would fail % rfi-p> more % 4th MORE would loop % true % [1,2,a] % like: for the conjunction % I = [1] % I = [1] % apprel(I,J, F), % J = [2,a] % J = [2,a] % [1,2,a] is F % rfi-p> revfun(tup(a,b|V)) % A function called with a non-ground "|"-list. % [b,a] % Returned value no. 1 is ground (variableless) % V = [] % because V can be bound to the empty list. % rfi-p> more % The request for MORE solutions (PROLOG's ";") % [H*15,b,a] % returns a 3-list pattern starting with H*15, % V = [H*15] % a (free) variable also occurring in V. % rfi-p> more % Another MORE (of infinitely many successes) % [H*24,H*26,b,a] % now returns a non-ground list of length 4, % V = [H*26,H*24] % whose first two elements reverse those in V.