错误的原因是 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/3
或findall/3
重新构建列表。