有没有办法配置YAP(和/或SWI prolog),以便它们在任何调用term_to_atom/2?中保留变量名称.
例如,当我执行此操作时:
term_to_atom(member(X, [1,2]), A).
Run Code Online (Sandbox Code Playgroud)
我得到了这个答案:
A = 'member(_131405,[1,2])'
Run Code Online (Sandbox Code Playgroud)
哪里X被其内部代表所取代.
但是,我想得到这个答案:
A = 'member(X,[1,2])'
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助!
fal*_*lse 11
涉及两个问题.如何将变量名称X放入系统,以及如何将具有此类变量的术语放入原子中.
在X你输入是通过将它转换为不具有关联的名称的常规变量顶层读取.让我们在YAP中看到:
?- read(Term).
|: X+3*Y+X.
Term = _A+3*_B+_A
Run Code Online (Sandbox Code Playgroud)
该|:是YAP的提示输入.我们已输入X+3*Y+X. 但是,变量Term包含_A和_B(由顶级选择的名称)代替X和Y.因此,一旦读取/ 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
Run Code Online (Sandbox Code Playgroud)
因此,read选项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).
Run Code Online (Sandbox Code Playgroud)
这么多的阅读.
现在写作.我们不能直接写这个术语,但必须随附列表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'.
Run Code Online (Sandbox Code Playgroud)
变量_131284看起来非常难看.要获取与其名称相关联的变量以进行打印,我们可以实现term_to_atom/3如下:
term_to_atom(T, Eqs, A) :-
with_output_to(atom(A), write_term(T,[variable_names(Eqs),quoted(true)]) ).
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
?- 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
Run Code Online (Sandbox Code Playgroud)
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).
Run Code Online (Sandbox Code Playgroud)
以下是针对6.3.4之前的YAP的ISO不兼容的解决方案.它不再是必要的.至于与单独写入选项的差异:term_to_atom/3如下定义会干扰约束并且无法正确呈现'$VAR'/1.
但目前我们只能接近理想的选择
variable_names/1.为了我们自己的变量名打印而言,变量都通过YAP被替换'$VAR'(Codes)其中Codes的字符代码列表.这不完全一样,但它非常接近.这进入一个文件:Run Code Online (Sandbox Code Playgroud):- 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中.