next up previous contents
Next: Powerful Features ---Comparisons Up: Powerful Features ---Splitting Previous: arg/3

=../2

Now =.. is pronounced ``univ''. It can be used to map a term onto a list in this way:

Term [ Functor, Arg, Arg, ... Arg]
For example, =../2 can be used with mode =..(+,+) and mode =..(+,-):
 
?- foo(12,fred)=.. [foo,12,fred].

yes

?- fact(male(fred),23)=.. X

X= [fact,male(fred),23]

The predicate can also be used with mode =..(-,+).
 
?- X=.. [fact,male(fred),23].

X = fact(male(fred),23)

Here are some more examples:
 
?- (a + b) =.. X.

X = [+, a, b]

?- [a,b,c] =.. X.

X = ['.',a,[b,c]]

We demonstrate a real application where we have a predicate triple_one/2 which takes as input an integer (first argument) and outputs (second argument) its triple. We are going to use =../2 to triple each element of an input list. This will mimic the behaviour of a predicate triple/2 previously used as an example. We define a predicate map/3 which takes a predicate name as its first argument, the input list as the second argument and returns the output list as the third argument as in:
 
?- map(triple,[1,2,3],X).

X=[3,6,9]

We give the special case with the first argument as triple and then generalise it.
 
map(triple,[],[]).

map(triple,[H1T1],H2T2]):-

X=.. [triple,H1,H2],

call(X),

map(triple,T1,T2).

The main trick is to assemble a term looking like triple(H1,H2) using =../2 and then use call/1 to execute the goal.

Now we replace the specific reference to triple and provide a more general version that can handle the task for arbitrary predicates of arity 2 ---provided that they are defined to work with mode predname(+,-).

 
map(Functor,[],[]).

map(Functor,[H1T1],H2T2]):-

X=.. [Functor,H1,H2],

call(X),

map(Functor,T1,T2).

The next task is to allow for an even more general version that can do the same sort of thing for predicates with an arity of more than two!

For example, define a predicate npl/3 that takes a positive integer as first argument and a number as its second argument, returning the third argument as the second argument `npled' as in:

 
?- nple(7,5,X).

X=35

We define nple/3:
 
nple(Multiplier,In,Out):- Out is Multiplier*In.
 [-5pt]

Now to look at the code. Now, we need to give the new version of map/3 a first argument which contains the necessary info --- viz the name of the predicate and the constant multiplier.

We can do this as the term nple(N) where N is the multiplier. We transform the term nple(N) into a list [nple,N] and then append the two arguments H1 and H2 using the standard append/3. This list is then rebuilt as the term nple(N,H1,H2) and then executed via call/1.

 
map(nple(N),[],[]).

map(nple(N),[H1T1],[H2T2]):-

nple(N)=.. List,

append(List,[H1,H2],NewList),

X=.. NewList,

call(X),

map(nple(N),T1,T2).

Nowhere does this really depend on the arity of nple(N) ---so we just replace the term nple(N) by Term.
 
map(Term,[],[]).

map(Term,[H1T1],[H2T2]):-

Term=.. List,

append(List,[H1,H2],NewList),

X=.. NewList,

call(X),

map(Term,T1,T2).



next up previous contents
Next: Powerful Features ---Comparisons Up: Powerful Features ---Splitting Previous: arg/3



Paul Brna
Mon May 24 20:14:48 BST 1999