如何重用Prolog数据结构?

时间:2013-09-12 00:14:38

标签: prolog

我正在使用Prolog编写一个小程序。我想重用一个数据结构,所以我尝试将它分配给变量:

CitizenProfile = voter_profile(citizen,not_in_prison).

然后我像这样使用它:

state(alabama, [CitizenProfile]).

但是,当我从控制台编译文件时遇到此错误:

**[No permission to modify static_procedure `(=)/2'][1]**
==

我甚至尝试声明等号动态,但这并没有解决任何问题。 :(

:- dynamic (=)/2.

2 个答案:

答案 0 :(得分:2)

错误的原因是它看起来像你正试图这样做Prolog:

=(CitizenProfile, voter_profile(citizen,not_in_prison)).

这看起来就像任何其他事实定义一样。 =/2可以很容易foobar/2

foobar(CitizenProfile, voter_profile(citizen,not_in_prison)).

现在,如果我们处于某个规则体的中间,这可能是建立变量绑定的合法方式。然后一切都会达到高潮:

foo :- ...,
    CitizenProfile = voter_profile(citizen,not_in_prison),
    state(alabama, [CitizenProfile]).

这与说这句话是一样的:

foo :- ...,
    state(alabama, [voter_profile(citizen,not_in_prison)]).

如果这个扩展是你想要完成的,那么很遗憾没有办法在像这样的事实数据库中创建速记。正如@hardmath所说,你可以使用assertz/1来完成它,看起来像这样:

make_database :-
    CitizenProfile = voter_profile(citizen,not_in_prison),
    assertz(state(alabama, [CitizenProfile])).

这可能是一种粗略的行为,因为你将静态信息放入动态商店。根据我的经验,人们通常不希望在数据库中构建大型结构。它通常更清晰,更容易建立几个关系,并以关系方式“加入”它们。我不确定你在这里想要的是什么,所以这只是一个草图,但这是我期望看到的:

voter_profile(voter1, alabama,    citizen, not_in_prison).
voter_profile(voter2, alabama,    citizen, in_prison).
voter_profile(voter3, new_mexico, citizen, not_in_prison).

而不是我认为你将要建造的(最终),我想象的更像这样:

 state(alabama,   [voter_profile(citizen,not_in_prison), voter_profile(citizen, in_prison)]).
 state(new_mexico,[voter_profile(citizen,not_in_prison)]).

创建一堆列表的诱惑是可以理解的,但Prolog的数据库无法真正帮助您处理它们。你最终将采用大量的member/2和O(N)搜索,这将导致非常糟糕的性能。默认情况下,Prolog将对第一个参数进行索引,但是每个实现都定义了一些索引声明,您可以使用这些声明来为其添加或替代索引第二个或第N个参数。如果您需要所有结果,则可以使用bagof/3findall/3重新构建列表。

答案 1 :(得分:0)

您可能想要的是定义动态谓词voter_profile/2assertz新事实“动态”以便由该谓词存储(子句数据库)记住。我说“可能”是因为你还没有说清楚一个州(例如阿拉巴马州)应该如何与特定的公民形象相关。

有关SWI-Prolog内置assertz/1文档以及有关SWI-Prolog数据库机制的更多信息,请参阅here