¿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)
dondeCodes
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)
porN = Ch
. e instala lalibrary(lambda)
primero. Está preinstalado en YAP.