我想编写一个函数(道歉可能没有在这里使用正确的术语)wubble
这对于那些常量的特定常量和是真的如果包裹成另一个常数,但只有一层深!例子:
% are supposed to be TRUE:
?- wubble(foo).
?- wubble(bar).
?- wubble(wrapper(foo)).
?- wubble(wrapper(bar)).
% are suppoed to be FALSE:
?- wubble(not_in_knowledge_base).
?- wubble(wrapper(wrapper(foo))).
天真(至少在我脑中)的实现看起来像这样:
wubble(foo).
wubble(bar).
wubble(wrapper(wrapper(_))) :- !, fail.
wubble(wrapper(X)) :- wubble(X).
这适用于上面的查询。但是,我无法使用此实现枚举X
的所有有效wubble
:
?- wubble(X).
X = foo
X = bar
因此缺少X = wrapper(foo)
和X = wrapper(bar)
。是否有可能以某种方式修复我的实现?
答案 0 :(得分:4)
您可以将事实与规则分开:
wubble_(foo).
wubble_(bar).
wubble(X) :- wubble_(X).
wubble(wrapper(X)) :- wubble_(X).
答案 1 :(得分:2)
正如OP所指出的,在这个特殊情况下的一个解决方案如下:
wubble(foo).
wubble(bar).
wubble(wrapper(X)) :- wubble(X), ((X = wrapper(_), !, fail); true).
由于他也要求对这种模式进行解释,这是我最好的镜头:
鉴于上述知识库,wubble(X).
这样的查询会从上到下查看与目标wubble(X)
统一的事实或规则主管。如果它找到了一个事实,例如wubble(foo)
,那么目标就会成功,将X
与事实的内部术语统一起来,在这种情况下foo
。之后,我们可以告诉Prolog回溯到最后的选择点(Prolog在此过程中构建的深度优先搜索树中的节点),在这种情况下由原始目标{{给出1}}并让它寻找该目标的其他解决方案。如果我们在这里这样做,我们当然会得到第二个常数wubble(X)
的事实。
现在为有趣的部分。如果我们再次回溯,那么满足目标wubble(bar)
的唯一方法就是满足你的规则的前提。现在让我们机械地完成这个。这可能会令人惊讶,但wubble(X)
与wubble(wrapper(X))
结合在一起;你必须将这些wubble(X)
视为独立的。在查询X
和规则定义wubble(X)
的情况下,wubble(wrapper(X)) :- ...
都只是本地名称。实际上,这两个变量在这种情况下是独立的,未经实例化的变量,并且由于未实例化的变量基本上与所有内容相结合,因此我们有X
,因此规则的头部与我们的查询匹配。我们现在应该分别为查询和规则调用X = wrapper(X)
和X1
。
现在规则的尾部是一个连词,所以我们首先尝试满足第一个目标X2
,这会创建一个新的选择点。现在,这个过程基本上重新开始:我们从上到下搜索知识库,找出与之相结合的东西,首先找到wubble(X)
。因此,wubble(foo)
现已与X2
统一,我们会检查现在与foo
合并的第二部分是否成功,因为X2 = foo
。因为合并的两个目标都成功foo \= wrapper(_)
,我们的原始目标也会成功X2 = foo
。
从这里回溯基本上将我们带回到第二个选择点,由规则中的第一个目标创建。接下来,我们找到X1 = wrapper(X2) = wrapper(foo)
,它会再次检查结合的第二部分,我们的原始目标会成功X2 = bar
。
接下来,我们再次达到规则;我们统一X1 = wrapper(bar)
,我们的新目标是X2 = wrapper(X3)
,创建一个新的选择点,这会成功wubble(X3)
,第二部分也会检出。所以现在我们进入一层,我们有X3 = foo
。这不符合第二部分的结合!它会触发X2 = wrapper(foo)
,因此我们!, fail
的原始目标,即我们统一wubble(X1)
,失败。但不仅如此,我们还会削减,这消除了第一次递归X1 = wrapper(X2) = wrapper(wrapper(foo))
调用及其下方所有内容的选择点,因此我们甚至不再尝试kipple
或X3 = bar
。< / p>
所以我们回到目标X3 = wrapper(X4)
的原始选择点;但是数据库中没有与此相匹配的条款,所以我们已经完成了。
现在我知道这可能很难以文本形式出现,所以这是我尝试可视化搜索树: