Newsgroups: comp.lang.prolog
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!oitnews.harvard.edu!purdue!lerc.nasa.gov!magnus.acs.ohio-state.edu!math.ohio-state.edu!howland.reston.ans.net!newsfeed.internetmci.com!in1.uu.net!allegra!alice!pool-pereira.research.att.com!user
From: pereira@research.att.com (Fernando Pereira)
Subject: Re: findall without copying?
X-Nntp-Posting-Host: pool-pereira.research.att.com
Message-ID: <pereira-2311951711110001@pool-pereira.research.att.com>
Sender: usenet@research.att.com (netnews <9149-80593> 0112740)
Organization: AT&T Bell Laboratories
References: <48tpdt$fi1@lyra.csx.cam.ac.uk>
Date: Thu, 23 Nov 1995 22:11:11 GMT
Lines: 53

In article <48tpdt$fi1@lyra.csx.cam.ac.uk>, etg10@cl.cam.ac.uk (Edmund
Grimley-Evans) wrote:

> I have the problem that I have a neat, perspicuous and elegant way
> of doing something with findall, but unfortunately it's hopelessly
> inefficient because of the way findall copies its solutions. Or
> worse still it's unusuable because I have to preserve the identity
> of variables.
> 
> A very simple example of the problem might be:
> 
> tail(A,A).
> tail([_|A],B) :- tail(A,B).
> 
> tails(X,Y) :- findall(A,tail(X,A),Y).
> 
[...]
> What I really want is:
> 
> tails1(List,[List|Rest]) :- tails2(List,Rest).
> 
> tails2([],[]).
> tails2([_|Rest],[Rest|More]) :- tails2(Rest,More).
[...]
> Is there any general way of getting all solutions without copying
> all of the structures? (I can see that a non-copying-findall would
> not even be well-defined, but is there some other systematic
> approach that I could adopt in this sort of situation?)
findall/3 is an "or" iterator, while what you want is an "and" iterator,
in the style of the fold family of higher-order functions in functional
programming. Assume for the moment that your Prolog has a built-in
"higher-order" call (this can be provided or simulated in various ways,
cf. the discussions on call/N in this list some time ago). Assume we have
the library predicate:

   map(_Pred, [], Result, Result).
   map(Pred, [Elem|Rest], Result, Result0) :-
      Pred([Elem|Rest], Result1, Result),
      map(Pred, Rest, Result1, Result0).

and then define

   tails(List, Tails) :- map(tail, List, Tails, []).

   tail([_|Tail], Tails, [Tail|Tails]).

Many variants of this are possible and have been used.

-- 
Fernando Pereira
2B-441, AT&T Bell Laboratories
600 Mountain Ave, Murray Hill, NJ 07974-0636
pereira@research.att.com
