Есть две проблемы.Как вставить имя переменной 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.