1

I have a term, say a(t1,t2,t3) which I variabilize using numbervars/3. Then I need to extract the variables of the term, but the variables appear as:

a('$VAR'(0),'$VAR'(1),'$VAR'(2)) 

The problem is that prolog doesn't seem to recognize these terms as variables:

?- term_variables(a('$VAR'(0),'$VAR'(1),'$VAR'(3)),L). L = []. 

Or even simpler:

?- var('$VAR'(0)). false. 

On the other hand, if I use copy_term/2, it sees the variables correctly, but still term_variables/2 won't extract them:

?- copy_term(a('$VAR'(0),'$VAR'(1),'$VAR'(3)),Term),term_variables(Term,Vars). Term = a(A, B, D), Vars = []. 

Does anyone has any idea what I am doing wrong? I'm really stuck and I can't work further in the program I'm developing because of this.

Thank you very much in advance.

1 Answer 1

4

I'm unsure about how you're using numbervars/3, which is implemented so as to "...unify the free variables of [a term] with a term $VAR(N)", which can't be used directly to turn the term a(t1,t2,t3) into a('$VAR'(0),'$VAR'(1),'$VAR'(2)) as you suggest, unless t1, t2 and t3 are your place-holders for distinct variables.

The terms '$VAR'(N) that SWI's numbervars/3 generates are indeed terms, and not variables (as described in the manual), so can't be treated as variables.

Note that, if you see this:

?- copy_term(a('$VAR'(0),'$VAR'(1),'$VAR'(3)),Term). Term = a(A, B, D). 

What is happening is that the line Term = a(A, B, D). is being written via something like write_term/2 to the console, which can be configured to portray certain terms like '$VAR'(N) as named variables (which can be misleading). Notice that if you try this instead:

?- copy_term(a('$VAR'(0),'$VAR'(1),'$VAR'(3)),Term), write_term(Term, [numbervars(false)]). a($VAR(0), $VAR(1), $VAR(3)) Term = a(A, B, D). 

The call to write_term/2 here explicitly disables the numbervars option, and prints out the true bindings of the arguments of the a/3 term, which are indeed $VAR(N) terms. The next line printed to the console (i.e., Term = a(A, B, D)) is doing something akin to enabling the numbervars option instead (perhaps for readability).

If you need to 'variablize' a term, I can suggest something along these lines instead:

% takes a term T, a list of [Term:Variable] replacements R, and makes V: variablize(T, R, V) :- member(R0:V, R), R0 == T, !. variablize([T|Ts], R, [NT|NTs]) :- !, variablize(T, R, NT), variablize(Ts, R, NTs). variablize(T, R, NT) :- compound(T), !, T =.. [F|As], variablize(As, R, NAs), NT =.. [F|NAs]. variablize(T, _, T). 

Example:

?- variablize(a(t1,t2,t3), [t1:X, t2:Y, t3:Z], T). T = a(X, Y, Z). 

This assumes that you know which sub-elements (e.g., t2) you want replaced, and with which variables. This particular implementation could more accurately be called replace/3, as it will find-and-replace any sub-element occurrence in the input term (even if they are other variables!).

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much for your reply. What you propose does not help much, since I do not know the term I have to variabilize. I have to construct clauses matching some syntactic bias from knowledge, then variabilize and generalize. I use numbervars(,N,), where N is 0 for the first variable and increazed for each new, then create a varbed term using the initial functors.But I need to get the vars from the variabilized term . I resorted to a stupid method, writting the vared term in a file, then reading it and getting the vars. Any other suggestions are really welcome.
Your variablize is a pretty neat piece of code. I wish I could attain this level of Prolog proficiency!
Thanks! I hope it's helpful. I've been programming Prolog professionally full-time for several years ;)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.