On 07/24/2014 07:55 AM, Jonathan Avery wrote:
> I have actually thought up my own solution to this recently :D.
> I made a general mapping predicate I called myMap:
>
> doMember(Relation,MemberOfList,List,Result) :-
> member(MemberOfList,List), call(Relation).
> myMap(Relation,MemberOfList,List,Result,ResultList):-
> findall(Result,doMember(Relation,MemberOfList,List,Result),ResultList).
>
> And here is an example of a query:
> myMap(concat('a ', X, Y), Y, ['a dog', 'a cat'], X, Solutions).
> which yeilds:
> Solutions = [dog, cat].
>
>
> As you can probably see, this can be used more arbitrarily as in:
> myMap(findall([A,B],concat(A,B,C),X), C, [a,ab,abc], X, Solutions).
> which yeilds:
> Solutions = [[['', a], [a, '']], [['', ab], [a, b], [ab, '']], [['',
> abc], [a, bc], [ab, c], [abc, '']]].
>
> I hope you like this! :D
It is one of the many things one can do. There are several issues with
this. One is that it is failure driven. That has two disadvantages:
you cannot combine this with constraints (in most cases) and a possible
failure of your mapping relation just causes the element to be dropped
silently. The other is that findall/3 needs to copy the result, which
can be painful if it concerns a large term.
You can implement the above as a loop, but that requires a copy of the
mapping goal for each iteration to get fresh copies of the variables.
That is the same problem that library(lambda) is suffering from.
Other alternatives are list comprehension (B-Prolog) and logical loops
(ECLiPSe and SICStus). These have their own logical issues as pointed
out by Ulrich Neumerkel on this list, but the advantage is that they
can be compiled by goal-expansion, so there is no runtime overhead.
Maybe we should provide all these alternatives as packs. Anyone? I'm
still hoping that a really good solution comes along: one that does not
do backtracking, no copy_term, is readable, can be compiled and
meta-called and provides good performance. I don't think there is a
proof that this cannot exists. I think it can, but we would need
something more flexible than call/N. Call/N is the basis of maplist/N,
which has all these nice properties, except that it insists on adding
the fresh variables at the end of the arguments.
Cheers --- Jan
P.s. Your solution can also be compiled. Possibly the combination
of compilation and a copy-term/loop based implementation of
this interface is a good compromise? Comments?
> On Wednesday, July 23, 2014 11:35:31 AM UTC+12, kaitainjones wrote:
>
> I've never been sure if I've been missing something really obvious
> with maplist. If I had the predicate
>
> subtract( X, Y, Result )
>
> where Y was subtracted from X, is there a way in which I could e.g.
> subtract the value 3 from each element in a list using maplist/3? If
> I were using the predicate
>
> subtract_first_from_second( First, Second, Result )
>
> ...it would be easy enough to accomplish the following:
>
> ?- maplist( subtract_first_from_second( 3 ), [10,20,30], Out ).
> Out = [7, 17, 27].
>
> But is there a way I can achieve the same outcome using the first
> version of the predicate, i.e. without having a rewritten version of
> the predicate, in which the parameter I want to be a fixed value in
> the maplist comes first? (Obviously I could generate a list of 3s
> and use that as the second list arg in a maplist/4, but that would
> kinda suck.)
>
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to
swi-prolog+...@googlegroups.com
> <mailto:
swi-prolog+...@googlegroups.com>.