我一直在使用chr库和jpl接口.我有一个普遍的询问.我将来自SWI Prolog的约束发送到我的CHR程序中的java类的实例.例如,如果输入约束是leq(A,B),则变量的名称消失,并且出现的变量名称以_G开头.即使我尝试在不使用界面的情况下打印leq(A,B),也会发生这种情况.似乎每当处理变量时,名称将被替换为新名称.我的问题是,是否有办法做回映射.例如,是否有办法知道_G123对应于A等等.非常感谢你.
(这个问题与CHR无关,也不是SWI特有的).
Prolog系统完全丢弃编写Prolog程序时使用的变量名.原因是此信息不能用于准确打印变量.该变量可能有几个独立的实例.因此,需要为变量名添加一些唯一标识符.此外,在运行时维护该信息会产生大量开销.
要看到这一点,请考虑一个谓词mylist/1
.
?- [user].
|: mylist([]).
|: mylist([_E|Es]) :- mylist(Es).
|: % user://2 compiled 0.00 sec, 4 clauses
true.
Run Code Online (Sandbox Code Playgroud)
在这里,我们已经_E
为列表的每个元素使用了变量.toplevel现在使用唯一标识符打印所有这些元素:
?- mylist(Fs).
Fs = [] ;
Fs = [_G295] ;
Fs = [_G295, _G298] .
Fs = [_G295, _G298, _G301] .
Run Code Online (Sandbox Code Playgroud)
第二个答案可能会被打印出来Fs = [_E]
.但第三个呢?它不能打印,Fs = [_E,_E]
因为元素是不同的变量.所以Fs = [_E_295,_E_298]
我们可以获得最好的东西.但是,这意味着需要额外的预订.
但是还有另一个原因,为什么将源代码变量名称与运行时变量相关联会导致极端复杂:在不同的地方,该变量可能具有不同的名称.这是一个人为的例子来说明这一点:
p1([_A,_B]).
p2([_B,_A]).
Run Code Online (Sandbox Code Playgroud)
和查询:
?- p1(L), p2(L).
L = [_G337, _G340].
Run Code Online (Sandbox Code Playgroud)
你想要这两个元素应该有哪些名字?第一个元素可能有名称,_A
或者_B
甚至可能更好:_A_or_B
.或者,甚至_Ap1_and_Bp2
.这对谁有利?
请注意,顶级查询中提到的变量名称将被保留:
?- Fs = [_,F|_], mylist(Fs).
Fs = [_G231, F] ;
Fs = [_G231, F, _G375] ;
Fs = [_G231, F, _G375, _G378]
Run Code Online (Sandbox Code Playgroud)
所以有一种方法可以获得这些信息.关于如何在阅读术语时获取SWI和YAP中的变量名称,请参阅此问题.