Преобразование терминов в атомы с сохранением имен переменных в прологе YAP - PullRequest
4 голосов
/ 31 октября 2011

Есть ли способ настроить YAP (и / или пролог SWI), чтобы они сохраняли имена переменных при любом вызове term_to_atom/2?.

Например, когда я выполняю это:

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

Я получаю этот ответ:

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

Где X заменено его внутренним представлением.

Однако я хотел бы получить ответ вместо этого:

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

Спасибо за любую помощь!

1 Ответ

11 голосов
/ 31 октября 2011

Есть две проблемы.Как вставить имя переменной X в систему и как ввести термин с такой переменной в атом.

Введенный вами X читается верхним уровнем, который преобразует его вобычная переменная, с которой не связано имя.Давайте посмотрим, что в YAP:

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

|: является подсказкой YAP для ввода.И мы ввели X+3*Y+X. Однако переменная Term содержит _A и _B (имена, выбранные верхним уровнем) вместо X и Y.Таким образом, информация теряется и не может быть восстановлена ​​после того, как она будет прочитана с помощью read / 1.

Вы должны получить доступ к этой информации по-разному, с более общей встроенной функцией чтения read_term/2,3 и опцией variable_names/1.

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

Таким образом, опция чтения variable_names/1 дает вам информацию для восстановления имен переменных.Для каждой именованной переменной, считываемой read_term/2, существует структура Name = Variable, где Name - это атом, представляющий имя переменной.Выше 'X' - это заглавная буква X.

Анонимные переменные, то есть переменные с именем _, не встречаются в списке имен переменных.Их можно быстро извлечь, например, так:

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

Так много для чтения.

Теперь для записи.Мы не можем написать термин напрямую, но должны сопровождать его списком Eqs.Давайте назовем новый предикат term_to_atom(Term, Eqs, Atom).И в YAP, и в SWI есть with_output_to(Output, Goal), который записывает вывод Goal в различные пункты назначения, например atom(A).Так что теперь вы можете использовать write_term / 2, чтобы написать термин, как вам угодно.Пример:

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

Переменная _131284 выглядит очень некрасиво.Чтобы получить переменные, связанные с их именами для печати, мы можем реализовать term_to_atom/3 следующим образом:

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

И использовать его так:

   ?- 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 существует какопция записи в ISO, Minerva, Jekejeke, GNU, B, SWI, YAP и SICStus.

В SICStus, инициаторе записи терминов в списки, один пишет:

:- 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).

Следующее было несовместимым с ISO обходным путем для YAP до 6.3.4.Это больше не нужно.Что касается различий для отдельной опции записи: term_to_atom/3, как определено ниже, вмешивается в ограничения и неправильно отображает '$VAR'/1.

Но на данный момент мы можем только приблизить идеальный вариант variable_names/1.Чтобы напечатать термины с нашими собственными именами переменных, переменные должны быть заменены в YAP на '$VAR'(Codes), где Codes - список кодов символов.Это не совсем то же самое, но это очень близко.Это входит в файл:

:- 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) ).

Для SWI вам придется заменить atom_codes(N,Chs) на N = Ch.и сначала установите library(lambda).Он предварительно установлен в YAP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...