Rename specific variables in a term with new names

Hello,

I want to write a predicate rename_term_variables/3, which takes a term and a list of certain variables in the term as input and should output a new term where the variables in the list are renamed.

The following example illustrates the desired output of the predicate:

?- rename_term_variables(a(X, b(X, Y, Z)), [X,Z], New_Term).

New_Term = a(_7448, b(_7448, Y, _7450)).

Can anyone tell me how to write such a predicate?

Thanks in advance.

Not quite sure what you’re asking, but you might be interested in the variable_names option of read_term/2 and write_term/2. Also the numbervars/1 predicate and the numbervars options of write_term/2.

1 Like

Peter,

Thanks for suggesting to use the numbervars/1 predicate. The following code works for me:

rename_term_variables(Term, Vars, New_Term) :-
	numbervars(Vars),
	New_Term = Term.

?- rename_term_variables(a(X, b(X, Y, Z)), [X,Z], New_Term).
X = A,
Z = B,
New_Term = a(A, b(A, Y, B)).

The quick way probably goes along this route:

  • use term_variables/2 to get the vars of the term
  • use copy_term/2 to get a fresh fully separate copy.
  • use term_variables/2 on the copy to get the vars of the term
  • unify the variables of the copy that need not be renamed.
1 Like

Thanks, Jan, that works.

Here is the code that works:

rename_term_variables(Term,V,New_Term) :-
	term_variables(Term, V1),
	copy_term(Term, New_Term),
	term_variables(New_Term, V2),
	unify_var(V,V1,V2).

unify_var(_,[],[]) :- !.
unify_var(V,[H1|T1],[H2|T2]) :-
	( \+needed_var(H1,V) ->
		H2 = H1
	;	true
	), unify_var(V,T1,T2).

needed_var(_,[]) :- fail.
needed_var(H,[HV|TV]) :-
	( H == HV ->
		!
	;	needed_var(H,TV)
	).

?- rename_term_variables(a(X, b(X, Y, Z)), [X,Z], New_Term).
New_Term = a(_3306, b(_3306, Y, _3316)).