我正在尝试编写一个管理键值存储的关系序言程序。初始代码取自我在互联网上找到的一些讲座幻灯片(http://people.eng.unimelb.edu.au/pstukey/book/course.html - 请参阅:使用数据结构幻灯片)。
newdic([]).
addkey(D0,K,I,D) :- D = [p(K,I)|D0].
delkey([],_,[]).
delkey([p(K,_)|D],K,D).
delkey([p(K0,I)|D0],K,[p(K0,I)|D]) :-
dif(K, K0), delkey(D0,K,D).
这段代码允许用同一个键添加多个值——这对我来说很好。但是,它也会两次添加相同的键、值对,例如
?- newdic(D), addkey(D, a, 1, D2), addkey(D2, a, 1, D3), lookup(D3, a, X).
D = [],
D2 = [p(a, 1)],
D3 = [p(a, 1), p(a, 1)],
X = 1
D3 包含两次 p(a,1)。
为确保不会发生这种情况,我添加了以下代码;并且为了确保回溯找不到替代的 addkey 子句,我在第一个子句的末尾添加了一个剪切。
对于纯粹的关系程序来说,这是公平的游戏吗?或者是确保不添加重复键、值对的更好方法——而不使用切割。
newdic([]).
addkey(D0,K,I,D0) :- lookup(D0, K, I), !. % if the key already do nothing
addkey(D0,K,I,D) :- D = [p(K,I)|D0].
delkey([],_,[]).
delkey([p(K,_)|D],K,D).
delkey([p(K0,I)|D0],K,[p(K0,I)|D]) :-
dif(K, K0), delkey(D0,K,D).
这导致以下结果:
?- newdic(D), addkey(D, a, 1, D2), addkey(D2, a, 1, D3), lookup(D3, a, X).
D = [],
D2 = D3, D3 = [p(a, 1)],
X = 1.
不,有更多解决方案可用——程序立即返回。
任何建议都非常感谢,
丹尼尔
注意:顺便说一句:如果我为相同的键添加不同的值,则剪切确实允许回溯以识别相同键的第二个值:
?- newdic(D), addkey(D, a, 1, D2), addkey(D2, a, 1, D3), addkey(D3, a, 2, D4), lookup(D4, a, X).
D = [],
D2 = D3, D3 = [p(a, 1)],
D4 = [p(a, 2), p(a, 1)],
X = 2 ;
D = [],
D2 = D3, D3 = [p(a, 1)],
D4 = [p(a, 2), p(a, 1)],
X = 1.