Prolog的语法使用<head> :- <body>
格式作为规则:
tree(G) :- acyclic(G) , connected(G).
,表示G作为树的状态取决于非循环和连接的状态。
这种语法可以隐含的方式扩展到事实。遵循相同的例子:
connected(graphA)
建议connected(graphA):-true.
从这个意义上说,人们可能会松散地将Prolog事实定义为始终如实的Prolog规则。
我的问题:在任何情况下,一个脱胎规则(在所有情况下都被假定为真实的规则)是否合适?从语法上讲,这样的规则如下:
graph(X).
(建议graph(X):-true.
)
答案 0 :(得分:3)
事实上只是一个脱胎规则,正如你所说的那样。是的,有很多用于脱胎事实的用例:
而不是一些大括号语言伪代码
boolean is_three(integer x) { if (x == 3) { return true; } else { return false; } }
我们可以简单地写
is_three(3).
答案 1 :(得分:3)
在回答之前,重新解释一下你的问题:
在Prolog中,您是否会编写一条规则,除了头部中的匿名变量之外什么都没有?没有正文?
术语在这里很重要。 事实只是规则,只有 head 而没有 body (这就是为什么你的问题有点令人困惑的原因) )。 匿名变量是您明确告诉编译器在谓词子句的上下文中忽略的变量(谓词子句是变量的语法范围)。如果您尝试将此谓词子句提供给Prolog编译器:
foo(Bar).
你会得到一个“单例变量”警告。相反,你可以写
foo(_).
这告诉编译器这个参数是故意忽略的,不应该尝试使用变量绑定。
在操作上,当Prolog试图证明规则时会发生什么?
正如您所看到的,第二步使得这是一个递归定义的算法:证明规则的主体意味着证明其中的每个规则。
提出你的问题:这是什么意思:
foo(_).
有一个谓词
foo/1
,对于任何参数都是如此,因为在头部没有变量绑定,并且总是如此,因为不需要证明子目标。
我至少看到过这样一条规则的用法:看this section of the SWI-Prolog manual的最底层。小代码示例如下:
term_expansion(my_class(_), Clauses) :-
findall(my_class(C),
string_code(_, "~!@#$", C),
Clauses).
my_class(_).
您应该阅读链接文档以了解执行此操作的动机。代码本身的目的是将在编译时事实表添加到Prolog数据库中。这是通过术语扩展来完成的,这是一种代码转换机制,通常用于term_expansion/2
。您需要my_class/1
的定义,以便term_expansion/2
可以获取,转换它,并用扩展代码替换它。我强烈建议你把上面的剪辑,把它放在一个文件中,查阅它并使用listing/1
来查看效果是什么。我明白了:
?- listing(my_class).
my_class(126).
my_class(33).
my_class(64).
my_class(35).
my_class(36).
true.
NB :在此示例中,您可以用任何内容替换my_class(_)
的两次出现。你可以写得很好:
term_expansion(foobar, Clauses) :-
findall(my_class(C),
string_code(_, "~!@#$", C),
Clauses).
foobar.
最终结果相同,因为操作含义相同。但是,使用my_class(_)
是自我记录的,并且使代码的意图更加明显,至少对于经验丰富的Prolog开发人员来说,作为SWI-Prolog的作者;)。
答案 2 :(得分:1)
这通常是表达递归定义的基本情况的方式。
答案 3 :(得分:0)
为了突出我最初寻找的内容,我将为那些可能会发现自己在未来提出初步问题的人提供以下简短答案。
正如@Anniepoo建议的那样,脱胎规则的一个例子是递归定义的基本情况。查看谓词的示例,成员(X,L)用于说明:
member(X,[X|T]). /* recursive base case*/
member(X,[H|T]):- member(X,T).
此处,成员规则的第一个条目表示终止基本案例 - 与剩余列表的头部匹配的感兴趣项目X.
我建议访问@Boris的答案(接受)以获得更完整的治疗。