Conversión de términos a átomos preservando los nombres de las variables en el prólogo YAP

¿Hay alguna forma de configurar YAP (y / o SWI Prolog) para que conserven nombres de variables en cualquier llamada a term_to_atom/2 ?

Por ejemplo, cuando ejecuto esto:

 term_to_atom(member(X, [1,2]), A). 

Obtengo esta respuesta:

 A = 'member(_131405,[1,2])' 

Donde X ha sido reemplazado por su representación interna.

Sin embargo, me gustaría obtener esta respuesta en su lugar:

 A = 'member(X,[1,2])' 

¡Gracias por cualquier ayuda!

Hay dos problemas involucrados. Cómo obtener el nombre de variable X en el sistema y cómo obtener un término con dicha variable en el átomo.

La X que escribe es leída por el nivel superior que la convierte en una variable regular que no tiene un nombre asociado. Veamos eso en YAP:

  ?- read(Term). |: X+3*Y+X. Term = _A+3*_B+_A 

El |: es el mensaje de entrada de YAP. Y hemos ingresado X+3*Y+X. Sin embargo, la variable Term contiene _A y _B (nombres elegidos por el nivel superior) en lugar de X e Y Entonces la información se pierde y no se puede restaurar una vez que sea leída por read / 1.

Tienes que acceder a esa información de manera diferente con la función incorporada más general para leer read_term/2,3 y la opción variable_names/1 .

  ?- read_term(T,[variable_names(Eqs)]). |: X+3*Y+X. Eqs = ['X'=_A,'Y'=_B], T = _A+3*_B+_A 

Entonces la opción de lectura variable_names/1 le da la información para restaurar los nombres de las variables. Para cada variable nombrada leída por read_term/2 hay una estructura Name = Variable donde Name es un átomo que representa el nombre de la variable. Arriba, 'X' es el nombre capital X.

Las variables anónimas, es decir, las variables cuyo nombre es _ , no aparecen en la lista de nombres de variables. Se pueden extraer rápidamente así:

  ?- read_term(T,[variable_names(Eqs)]), term_variables(Eqs, Named), term_variables(Named+T, Vars), append(Named, Anons, Vars). 

Tanto para la lectura.

Ahora para la escritura. No podemos escribir el término directamente, pero tenemos que acompañarlo con la lista Eqs . Llamemos al nuevo predicado term_to_atom(Term, Eqs, Atom) . Tanto en YAP como en SWI hay with_output_to(Output, Goal) que escribe la salida de Goal en diferentes destinos como atom(A) . Entonces ahora puede usar write_term / 2 para escribir el término como lo desee. Un ejemplo:

 ?- with_output_to(atom(A),write_term('a b'+X,[quoted(true)])). A = '\'ab\'+_131284'. 

La variable _131284 se ve muy fea. Para obtener variables asociadas con sus nombres para imprimir, podemos implementar term_to_atom/3 siguiente manera:

 term_to_atom(T, Eqs, A) :- with_output_to(atom(A), write_term(T,[variable_names(Eqs),quoted(true)]) ). 

Y úsalo así:

  ?- read_term(T,[variable_names(Eqs)]), term_to_atom(T, Eqs, Atom). |: X+3*Y+X. Atom = 'X+3*Y+X', Eqs = ['X'=_A,'Y'=_B], T = _A+3*_B+_A 

variable_names/1 existe como una opción de escritura en ISO, Minerva, Jekejeke, GNU, B, SWI, YAP y SICStus.

En SICStus, el creador de escribir términos para las listas, uno escribe:

 :- use_module(library(codesio)). term_to_atom(T, Eqs, Atom) :- write_term_to_codes(T, Codes, [variable_names(Eqs),quoted(true)]), atom_codes(Atom, Codes). 

El siguiente fue un trabajo incompatible con ISO para YAP anterior a 6.3.4. Ya no es necesario. En cuanto a las diferencias con una opción de escritura separada: term_to_atom/3 como se define a continuación interfiere con las restricciones y no representa correctamente '$VAR'/1 .

Pero por el momento solo podemos aproximarnos a la opción ideal variable_names/1 . Para imprimir términos con nuestros propios nombres de variables, las variables deben sustituirse en YAP por '$VAR'(Codes) donde Codes es una lista de códigos de caracteres. Esto no hace exactamente lo mismo, pero está muy cerca. Esto va a un archivo:

 :- use_module(library(apply)). :- use_module(library(lambda)). write_eqs_term(T, Eqs) :- \+ \+ ( maplist(\Eq^( Eq = (N='$VAR'(Chs)), atom_codes(N,Chs)), Eqs), write_term(T,[numbervars(true),quoted(true)]) ). term_to_atom(T, Eqs, A) :- with_output_to(atom(A), write_eqs_term(T, Eqs) ). 

Para SWI, tendría que reemplazar los atom_codes(N,Chs) por N = Ch . e instala la library(lambda) primero. Está preinstalado en YAP.