Article View: comp.lang.prolog
Article #3735Re: In defence of difference-lists.
From: Mark Johnson
Date: Thu, 27 Oct 1988 13:25
Date: Thu, 27 Oct 1988 13:25
102 lines
4996 bytes
4996 bytes
I've received a couple of messages expressing interest in my
toy unfold/folder, so here's a longer description.
Here's a description of my little program: please remember that
it is only a first attempt at applying the Unfold/Fold transformation
automatically, and that as I note at the bottom of the article,
I think it can be improved considerably.
Even so, it is capable of performing the following Unfold/Fold transformations
on programs like (naive) reverse, the program "string" shown below,
and other "simple" recursive programs to yield their difference list
counterparts.
string(n(X,Y),S) :- string(X,SX), string(Y,SY), append(SX,SY,S).
string(X,[X]) :- terminal(X).
terminal(a). terminal(b). terminal(c).
It consists of 3 major predicates. To make things simpler, I describe
each predicates' application to naive reverse as a running example:
Example Input program (as assertions in data base).
reverse([],[]) <- [].
reverse([E|Es],Rs) <- [ reverse(Es,Ms), append(Ms,[E],Rs) ].
1. foldDefn(GoalToFold,FoldDef)
This proposes a definition clause FoldDef for the folding process
based on the clauses for GoalToFold. FoldDef is currently computed
by examining the recursive clauses for GoalToFold.
foldDefn(reverse(_,_),FoldDef).
FoldDef = reverse_f(_2,_820,_8)<-[reverse(_2,_14),append(_14,_820,_8)] ;
FoldDef = reverse_f(_2,_0,_8)<-[reverse(_2,_14),append(_14,[_0],_8)] ;
FoldDef = reverse_f(_2,_0,_830,_8)<-[reverse(_2,_14),append(_14,[_0 | _830],_8)] ;
2. unfoldFoldDefn(FoldDef,GoalToFold,Unfoldeds)
This unfolds all instances of the GoalToFold in FoldDef to yield the
unfolded clauses. It also performs some elementary simplifications on
the result.
unfoldFoldDefn(reverse_f(_2,_820,_8)<-[reverse(_2,_14),append(_14,_820,_8)],
reverse(_,_),Unfoldeds).
Unfoldeds = [
reverse_f([],_4,_4)<-[],
reverse_f([_62 | _64],_4,_6)<-
[reverse(_64,_74),
append(_74,[_62],_12),
append(_12,_4,_6)]] ;
3. fold(Unfolded,Folders,Folded)
This folds the body of Unfolded by the bodies of Folders to yield Folded.
Folders includes equivalences which may be useful in the folding process
as well as FoldDef itself.
In our example, note that there is nothing to fold in the first clause of
Unfoldeds. Note the equivalences involving append that are given to the
folder: only the first of these is used here, the second is required when
folding the unfolded body of the FoldDef for the "string" predicate defined
above.
fold(reverse_f([_62 | _64],_4,_6)<-
[reverse(_64,_74),append(_74,[_62],_12),append(_12,_4,_6)],
[ [reverse_f(A1,B1,C1)]<-[reverse(A1,D1),append(D1,B1,C1)],
[append(X,[A|V],W)] <- [ append(X,[A],Y), append(Y, V, W) ],
[append(B,D,X),append(A,X,E)] <- [append(A,B,C),append(C,D,E)] ],
Folded).
Folded = reverse_f([_0 | _2],_8,_10)<-[append(_28,_8,_10),reverse_f(_2,[_0],_28)] ;
Folded = reverse_f([_0 | _2],_8,_10)<-[reverse_f(_2,[_0 | _8],_10)] ;
Folded = reverse_f([_0 | _2],_8,_10)<-[append(_16,[_0 | _8],_10),reverse(_2,_16)] ;
Folded = reverse_f([_0 | _2],_8,_10)<-[reverse_f(_2,_254,_10),append([_0],_8,_254)] ;
Folded = reverse_f([_0 | _2],_8,_10)<-
[append(_16,_254,_10),append([_0],_8,_254),reverse(_2,_16)] ;
Folded = reverse_f([_0 | _2],_8,_10)<-
[append(_28,_8,_10),append(_16,[_0],_28),reverse(_2,_16)] ;
The second of these answers is the preferred one, because it does not contain
either the original program predicate we are trying to redefine, or the
predicate "append".
The program might be improved in the following ways. First, step 1,
ie. choosing a FoldDef, should incorporate the constraint that
the FoldDef actually be capable of computing the relation to be
folded! This would rule out all but the first proposed FoldDef in step 1
of the example above, and more importantly, may prove useful as a way of
generating possible FoldDefs.
Second, the unfolding step (step 2) could be modified so that it
doesn't just do a single unfold of the FoldDef head, but instead
unfolds all goals that contain a "recursive argument" of the FoldDef.
With this extension, the procedure may be able to Unfold/Fold programs
that are more complicated than the simple "one-level" recursive ones
that it can deal with now.
Technical Details
Message-ID:
<6148@csli.STANFORD.EDU>Path:
arc1-ca.pugleaf.net!utzoo!attcan!uunet!lll-winken!lll-tis!helios.ee.lbl.gov!pasteur!agate!labrea!csli!johnsonReferences:
<3002@mulga.oz> <542@quintus.UUCP> <3005@mulga.oz> <2502@munnari.oz> <550@quintus.UUCP> <6087@csli.STANFORD.EDU>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!lll-winken!lll-tis!helios.ee.lbl.gov!pasteur!agate!labrea!csli!johnson From: johnson@csli.STANFORD.EDU (Mark Johnson) Newsgroups: comp.lang.prolog Subject: Re: In defence of difference-lists. Keywords: Difference-lists, Dataflow analysis, Program transformation. Message-ID: <6148@csli.STANFORD.EDU> Date: 27 Oct 88 13:25:05 GMT References: <3002@mulga.oz> <542@quintus.UUCP> <3005@mulga.oz> <2502@munnari.oz> <550@quintus.UUCP> <6087@csli.STANFORD.EDU> Reply-To: johnson@csli.UUCP (Mark Johnson) Organization: Center for the Study of Language and Information, Stanford U. Lines: 101