Typically, Prolog variables are assigned by the compiler “internal names”, so that it is impossible to sort them using their original names (those provided by the user or by an input file).
However, in LPA Win-Prolog it is possible to preserve the original variable names, as well as sort them on the basis of these names. Finally it is also possible to retrieve the variables with their original names. Some examples follow:
1) LPA Prolog has predicates handling variable names (eread/2 and eprint/2). E.g. if you want Prolog to read a term with variables, preserving user-given variable names and then printing them out, you can use code like this:
| ?- eread(EXP,Vars), nl, eprint(EXP,Vars), nl, nl, nl.
EXP = this(_38218,_38220,_38226,_38232) ,
Vars = [('THING',_38218),('V',_38220),('X',_38226),('W',_38232)]
In LPA Prolog, eread/2 reads a term with variables and the it produces a list of names-and-variables [(Name,Var)|…] as a second argument. This has elements like (‘THING’,_38218) -in this example- where ‘THING’ is the user-defined variable name and _38218 is an “internal variable code”, generated by the compiler. The second predicate eprint/2 is similar: If the second argument of eprint/2 is bound to the names-and-variables-list (extracted previously) then the result is a printout of the expression as it was originally entered, preserving all the user-defined variable names.
Now, here is another example, only slightly more complicated. This time, it uses a small source-code file, which you can create easily, by copying and pasting the code that follows into a text file (of extension ‘.pl’).
The program asks the user to type a list (consisting of variables and constants) and then it is required to sort the variables, finally printing-out the resulting list with Variables sorted, but with names exactly the same as those typed originally. So, here is a piece of code that reads such a list from a user-prompt, sorts the list with respect to its variables, and then prints out the resulting list, with all the variables sorted:
test:- repeat, write('type a list of variables and constants:'), nl,
eread(List,VL), sort(VL,VLsorted), sort(List,List1), varsort(List1,VLsorted,ListOut),
write('sorted w.r.t. variables: '), eprint(ListOut,VL), nl,
write('press escape to exit, any other key to go on: '), get0(CHAR), CHAR = -1, !.
removevar(V,[A|L],L):- V == A, !. removevar(V,[A|L],[A|Lx]):- removevar(V,L,Lx). varsort(,_,):- !. varsort(L,,L):- !. varsort(L,[(_Name,V)|VL],[V|XL]):- removevar(V,L,L2), !, varsort(L2,[(_,V)|VL],XL). varsort(L,[_|VL],XL):- !, varsort(L,VL,XL).
This piece of code is complete; you can copy it, paste it to a file ando compile it in LPA Win-Prolog. After doing this, type ‘test’ at the Prolog prompt. You will get a dialogue such as this:
| ?- test1. type a list of variables and constants: |: [A,D,C,2,B,34,X,F,D]. sorted w.r.t. variables: [A,B,C,D,F,X,2,34] press escape to exit, any other key to go on: |: yes
The main predicate ‘test’ calls ‘eread/2’, which reads user- (or file-) input expressions and parses them into Prolog terms with variables. Then the variable-name-list is sorted. The original list is also sorted, and then the sorted variable names’ list is used to rearrange the sorted original list a second time, this time sorting it as regards variable names.
A very crucial predicate here is ‘removevar/3’, which is similar to the built-in predicate ‘remove/3’, removing an element of a list and producing the list without this element each time it’s called. However, unlike the built-in predicate ‘remove/3’, this one only deletes list-elements which are “identical to the first argument”, without doing any unification. I.e. it is capable of removing variables, if they exist in the list (of arg 2) but does not confuse them with other variables through unification.
Another new predicate in the code above is ‘ varsort’. It assumes that arg-1 contains an input-list (a mixture of variables and constants) and it makes use of the sorted list of variable names, to rearrange the list so that all the variable names are sorted, in the third (output-)argument:
[A,D,C,2,B,34,X,F,D] becomes [A,B,C,D,F,X,2,34] .
As an exercise, if you have some Prolog experience you can now try to write a similar piece of code that works on ANY kind of Prolog term, not just a list. If you do write such code, you can also send it as a comment in this posting, or an e-mail to email@example.com (with your name and any other details you’d like to see included), and I will publish it in this blog (with your name or alias) exactly as you’ve written it (provided of course that… it works 🙂 )!