Reputation: 3743
How does one evaluate the result of a prolog predicate to pass as an argument? I am trying to write code to reverse pairs of elements in a list:
swap([A,B,C,D,E,F],R).
I want the result:
[B,A,D,C,F,E]
but I get this result:
append(append(append([],[B,A],[D,C],[F,E])))
Here is my code:
swap(L,R) :- swapA(L,[],R).
swapA([],A,A).
swapA([H,H2|T],A,R) :- swapA(T, append(A,[H2,H]), R).
Thanks.
Upvotes: 3
Views: 6318
Reputation: 22017
You can't call a Prolog predicate like a function. It doesn't return anything. When you pass append(A,[H2,H])
to swap, it interprets it as data, not as code.
A Prolog clause creates a relation between N logic variables. That means in theory there is no concept of "input" and "output" in Prolog predicates, you can make a query with any combination of instantiated and non-instantiated variables, and the language will find the meaningful relation(s) for you:
1 ?- append([a],[b,c],[a,b,c]).
true.
2 ?- append([a],[b,c],Z).
Z = [a, b, c].
3 ?- append([a],Y,[a,b,c]).
Y = [b, c].
4 ?- append(X,[b,c],[a,b,c]).
X = [a] ;
false.
5 ?- append([a],Y,Z).
Z = [a|Y].
6 ?- append(X,[b,c],Z).
X = [],
Z = [b, c] ;
X = [_G383],
Z = [_G383, b, c] ;
X = [_G383, _G389],
Z = [_G383, _G389, b, c] . % etc
7 ?- append(X,Y,[a,b,c]).
X = [],
Y = [a, b, c] ;
X = [a],
Y = [b, c] ;
X = [a, b],
Y = [c] ;
X = [a, b, c],
Y = [] ;
false.
8 ?- append(X,Y,Z).
X = [],
Y = Z ;
X = [_G362],
Z = [_G362|Y] ;
X = [_G362, _G368],
Z = [_G362, _G368|Y] . % etc
9 ?-
In practice, not every predicate can be called with every combination, due to limitations in expressing the relation in a way that will not yield an infinite loop. Other cause may be extra-logic features, like arithmetic. When you see a predicate documented like:
pred(+Foo, -Bar, ?Baz)
That means it expects Foo
to be instantiated (i.e. unified to another non-var), Bar
to be a free variable and Baz
can be anything. The same predicate can have more than one way to call it, too.
This is the reason you can't treat a Prolog relation as a function, in general. If you pass a compound as argument, the clauses will likely treat it just as a compound, unless it is specifically designed to handle it as code. One example is call/1
, which executes its argument as code. is
, =:=
, <
and other arithmetic operators do some interpretation too, in case you pass something like cos(X)
.
Upvotes: 3
Reputation: 7503
Several things:
'
: ['A','B','C','D','E','F']
Here is a suggestion:
swapA([], []).
swapA([X, Y|T], [Y, X|R]) :- swapA(T, R).
And consider adding another base case if you want your predicate to hold when you have an odd number of elements in your list:
swapA([X], [X]).
Upvotes: 8