Re: Meta Predicates and Variables in SWI Prolog

From: Bart Demoen (bmd_at_cs.kuleuven.ac.be)
Date: 03/31/04


Date: Wed, 31 Mar 2004 15:59:44 +0200

Michael David Pedersen wrote:
> Hi Bart,
>
> Thank you for your prompt reply.
>
>
>>Michael David Pedersen wrote:
>>
>>>However the list is being constructed at runtime and looks like
>>>['A','B',
>>>'_']. I thus need to convert this to a list of atoms as needed in the
>>>apply predicate.
>>>
>>
>>I would expect you to want to convert the list ['A', 'B', '_']
>>to a list of VARIABLES. No ?
>
>
> Right, I actually though that variables are atoms as well -- clearly, this
> is wrong (variables are terms).
>
>
>
>>>term_to_atom('A', Atom).
>>
>>term_to_atom is not what you need. You could use it as follows:
>>
>>?- term_to_atom(X,'A').
>>
>>and that will unify X with a free variable - but that doesn't
>>do much, does it ?
>>Moreover, if you do
>>
>>
>>?- term_to_atom(X,'A'), term_to_atom(Y,'A').
>>
>>X and Y will be DIFFERENT variables and that might not be what you want
>>...
>
>
> Right, this is not what I want.
>
>
>>Maybe you should consider changing the generation of the list in the first
>>place.
>
>
> But this is my problem -- I cannot find a way to do this. Maybe an excerpt
> from the code I am working with will help. I am trying to implement part
> of the relational algebra in prolog, and the following is a (simplified)
> example of how projection would work:
> -------------------------
> /********************
> Project is the top-level projection predicate
> ********************/
> project(Rel, AttrList) :-
> sort(AttrList, Sorted),
> pad(1, 3, Sorted, Padded),
> apply(Rel, PaddedAtoms). /** PROBLEM **/
>
> /**************************
> The pad predicate pads a sorted list of integers (x1, x2, ..., xn) with
> underscores so that each xi occurs on position i in the list. Furthermore,
> each xi is prepended with an 'A', so that it can be interpreted as a Prolog
> variable. Example where Arity=6:
>
> (1, 2, 5) -> ('A1', 'A2', '_', '_', 'A5', '_')
> ***************************/
> /* bottom case */
> pad(Arity, Arity, [X], [AX]) :-
> string_concat('A', X, AX).
>
> /* The next two predicates handle the case where underscores must be
> prepended */
> pad(Arity, Arity, [], ['_']).
>
> pad(Pos, Arity, [], ['_'|Xs]) :-
> Pos \== Arity,
> succ(Pos, Pos2),
> pad(Pos2, Arity, [], Xs).
>
> pad(Pos, Arity, [X|Xs], [AX|Ys]) :-
> Pos \== Arity,
> Pos == X,
> string_concat('A', X, AX),
> succ(Pos, Pos2),
> pad(Pos2, Arity, Xs, Ys).
>
> pad(Pos, Arity, [X|Xs], ['_'|Ys]) :-
> Pos \== Arity,
> Pos \== X,
> succ(Pos, Pos2),
> pad(Pos2, Arity, [X|Xs], Ys).
>
> /*************
> Here follows an example relation used to test the code above.
> *************/
> rela(a, b, c).
> rela(d, e, g).
> -------------------------
>
> project(rela, [1, 3]) should then return A1=a, A3=c and A1=d, A3=g which
> is what I want. However the list [1, 3] is the result of lexing and parsing,
> and hence it _IS_ on the form ['1', '3'] (and subsequently on the form
> ['A1', 'A2'] after coming through the pad predicate). So this still does not
> work in the apply predicate.
>
> Do you have any further ideas/hints on how to convert the list of character
> strings into a list of VARIABLES, as you correctly understood?
>
>
>>BTW, if you don't understand how term_to_atom works, try (to start with)
>>queries like
>>
>>?- term_to_atom(X,'f(asd,[X],3.14)').
>>
>>and
>>
>>?- term_to_atom(X,'f(asd,[X],3.14').
>
>
> What is the difference between the two queries (except a missing bracket,
> which causes a syntax error)?
>
> Thanks a lot for your help!
> Regards,
>
> Michael David Pedersen
>

I might have just what you need ...

pad(N,Max,Positions,VarsAtPositions,VarList) :-
         (N > Max ->
             VarList = [],
             VarsAtPositions = []
         ;
             VarList = [NewVar|RestVarList],
             N1 is N + 1,
             (Positions = [N|RestPositions] ->
                 VarsAtPositions = [NewVar|RestVarsAtPositions],
                 pad(N1,Max,RestPositions,RestVarsAtPositions,RestVarList)
             ;
                 pad(N1,Max,Positions,VarsAtPositions,RestVarList)
             )
         ).

/*

try
?- pad(1,6,[1,2,5],VarsAtPositions,VarList).

*/

rel(a, b, c).
rel(d, e, g).

project(PredName,Positions,VarsAtPositions) :-
         Max = 3, % you have to decide on the arity
         pad(1,Max,Positions,VarsAtPositions,VarList),
         Goal =.. [PredName|VarList],
         call(Goal).

/*

?- project(rel,[1,3],Out).

*/

Cheers :-)

Bart Demoen