gpt4 book ai didi

prolog - Prolog assert/1 对传递的术语做了什么?

转载 作者:行者123 更新时间:2023-12-02 09:07:49 25 4
gpt4 key购买 nike

我试图了解 assert 和 retract 对传递的术语有何作用。如果我运行以下命令:

?- assertz(item(first)).
true.

?- assertz(item(second)).
true.

?- assertz((item(Y) :- =(Y, third), writeln(Y))).
true.

?- retract(item(X)).
X = first ;
X = second ;
false.

retract/1 删除了所有项目,但我的 writeln/1 从未被调用,所以看起来 retract 实际上不是解析它传递的术语。看起来它正在执行一些特殊操作:

  • 统一术语与数据库中的唯一事实(即没有尾部的规则)
  • 在应用统一替换后撤回每一个

这样对吗?还是这里发生了其他事情?

换句话说:如果我编写自己的单参数规则,Prolog 不会自动将 item(X) 与数据库统一起来并遍历所有 item/1 的事实。它只是给了我项目(X)。 retract 是如何发挥其魔力的?

?- assertz((myRule(X) :- writeln(X))).
true.

? myRule(item(X)).
item(_2556)
true.

回答进一步澄清:根据 User9213 的回答,答案似乎是“收回(但不是断言!)有一个有趣的行为,它在对数据库执行某些操作之前对其术语进行简单的统一”。我想知道为什么我见过的其他内置函数(如 atom/1 和 writeln/1)似乎没有这样做。也许它比我经历过的更常见?

为了保持一致性,似乎 retract 应该有必需的基本条款,如果用户想做像我上面的例子那样的事情,他们可以这样做:

?- (item(X), retract(item(X))).

这一切让我觉得我遗漏了什么,或者这些内置函数的设计可能不一致?任何可以解释这一点的澄清都很好。

最佳答案

要加入我的声音,是的,所有这些谓词(assert*retract*)操纵 Prolog 的事实和规则数据库;他们不会评估他们的论点,就好像它们是事实或规则一样。是的,他们只是在他们的论点与数据库中的事实和规则之间进行“句法”统一。

Prolog 是一个 homoiconic language .程序可以像数据一样被操作;数据结构可以被解释为就好像它们是程序一样。最重要的是:某个结构是数据还是程序仅取决于上下文。

你似乎明白这一点,但对于下一个偶然发现你的问题和这个答案的可怜人,这里有一个玩具示例来演示。

有一个built-in predicate atom/1如果它的参数是一个原子,那么它就会成功:

?- atom(foo).
true.

?- atom(Bar). % Bar is a free variable, which is not an atom
false.

?- atom(atom(bar)). % atom(bar) is a compound term, which is not an atom
false.

但是 atom(bar) 在最后一个查询中只是一个复合词。它是一个具有仿函数原子/1 的复合项。它唯一的参数是一个原子。因此,如果您现在查询它:

?- atom(bar).
true.

还有这个非常好的谓词 called call .它使模糊程序和数据之间的界限变得更加容易。以下三个查询在含义上是相同的:

?- atom(bar).
true.

?- call(atom, bar).
true.

?- call(atom(bar)).
true.

此外,您可以动态地(在运行时)创建数据结构并将其作为程序进行评估。这是一个简单的 call/2 实现,它可以评估谓词,提供谓词名称和参数列表。它constructs the compound term using "univ"并通过将其放在子目标应该位于的位置来对其进行评估。我将其命名为 my_call/2 并使用 assertz 将其添加到数据库中:

?- assertz((my_call(Name, Args) :- Goal =.. [Name|Args], Goal)).
true.

?- my_call(between, [1, 3, X]).
X = 1 ;
X = 2 ;
X = 3.

你知道发生了什么吗? (注意:call 似乎是 Prolog 的一个相对较新的补充。在 call 广泛可用之前,如果你想元调用谓词,你必须使用这个技巧。我从经验中不知道这一点,只是根据我读过或听到的东西进行有根据的猜测,现在懒得引用。)


所以,让我们再试一次。实际上,事情要复杂得多,但非常简单:

Prolog 程序是一组谓词。未订购!

每个谓词都是一个子句列表。它是一个列表,因为谓词可能有 0 个或多个子句,并且它们有顺序。

子句可以是事实或规则。

规则是具有仿函数 :-/2 的复合项。是的,这是对的。明白我的意思:

?- assertz(:-(foo(X), between(1, 3, X))).
true.

?- listing(foo/1).
:- dynamic foo/1.

foo(A) :-
between(1, 3, A).

true.

这只是另一种写法。它更传统。

的确,这两者非常不同:

foo(X). % a fact
foo(X) :- between(1, 3, X). % a rule

你不能将一个与另一个统一起来。这就是为什么,如果你想收回 foo(X) :- between(1, 3, X),你不能只将 foo(X) 作为参数传递给收回。或者,要完成您的示例:

?- assertz(item(first)).
true.

?- assertz(item(second)).
true.

?- assertz((item(Y) :- =(Y, third), writeln(Y))).
true.

?- retract(item(X)).
X = first ;
X = second ;
false.

?- retract((item(X) :- X = Y, writeln(X))).
Y = third.

你现在看到了吗?

关于prolog - Prolog assert/1 对传递的术语做了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55943467/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com