在YAP-prolog中将术语转换为保留变量名的原子

在YAP-prolog中将术语转换为保留变量名的原子,prolog,Prolog,是否有办法配置YAP(和/或SWI prolog),以便在调用term\u to_atom/2时保留变量名 例如,当我执行此操作时: term_to_atom(member(X, [1,2]), A). 我得到的答案是: A = 'member(_131405,[1,2])' 其中,X已由其内部表示形式替换 然而,我想得到的答案是: A = 'member(X,[1,2])' 谢谢你的帮助 涉及两个问题。如何将变量名X放入系统中,以及如何将带有此类变量的术语放入atom中 您键入的X由顶层

是否有办法配置YAP(和/或SWI prolog),以便在调用
term\u to_atom/2
时保留变量名

例如,当我执行此操作时:

term_to_atom(member(X, [1,2]), A).
我得到的答案是:

A = 'member(_131405,[1,2])'
其中,
X
已由其内部表示形式替换

然而,我想得到的答案是:

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

谢谢你的帮助

涉及两个问题。如何将变量名
X
放入系统中,以及如何将带有此类变量的术语放入atom中

您键入的
X
由顶层读取,顶层将其转换为没有关联名称的常规变量。让我们在YAP中看到这一点:

   ?- read(Term).
   |: X+3*Y+X.
Term = _A+3*_B+_A
|:
是YAP的输入提示。我们已经输入了
X+3*Y+X。
但是,变量
术语
包含
\u A
\u B
(由顶层选择的名称)代替
X
Y
。因此,信息一旦被read/1读取,就会丢失,无法恢复

您必须以不同的方式访问这些信息,使用更通用的内置reading
read\u term/2,3
和选项
variable\u names/1

   ?- read_term(T,[variable_names(Eqs)]).
   |: X+3*Y+X.
Eqs = ['X'=_A,'Y'=_B],
T = _A+3*_B+_A
因此,读取选项
variable\u names/1
为您提供了恢复变量名称的信息。对于
read\u term/2
读取的每个命名变量,都有一个结构
Name=variable
,其中Name是表示变量名称的原子。上面,
'X'
是大写字母X的名称

匿名变量,即名称为
\uuu
的变量,不会出现在变量名称列表中。它们可以像这样快速提取:

 ?- read_term(T,[variable_names(Eqs)]),
    term_variables(Eqs, Named),
    term_variables(Named+T, Vars),
    append(Named, Anons, Vars).
阅读到此为止

现在开始写作。我们不能直接编写术语,但必须随附列表
eq
。让我们调用新谓词
term\u to_atom(term,Eqs,atom)
。在YAP和SWI中,都有一个将
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
在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).
以下是6.3.4之前YAP的ISO不兼容解决方案。不再需要了。至于与单独写入选项的区别:
term_to_atom/3
,如下定义会干扰约束,并且无法正确呈现
“$VAR”/1

   ?- read_term(T,[variable_names(Eqs)]).
   |: X+3*Y+X.
Eqs = ['X'=_A,'Y'=_B],
T = _A+3*_B+_A
但目前我们只能近似于理想的选择
变量名称/1
。要使用我们自己的变量名打印术语, 变量必须在YAP中用
'$VAR'(代码)
替换,其中
code
是字符代码的列表。这并不完全符合实际情况 相同,但非常接近。这将进入一个文件:

:- 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,您必须用
N=Ch
替换
atom_代码(N,Chs)
。 然后先安装。它预先安装在YAP中


谢谢你的回答。我有点困惑,你能给我举个例子吗?。我从你的回答中了解到,我应该使用的不是术语\u to \u atom/2,但我仍然不知道如何使用\u output \u to/2(对不起,我远不是Prolog专家:)我在ISO中找不到“$VAR”(字符串)。@CookieMonster:你的评论不再相关@差不多了。由于支持写入选项,$VAR不再与此问题相关。