0

我正在使用 Ivan Bratko 的书:“人工智能编程”在 Prolog 中研究 DCG 语法,我发现一些问题来理解 Prolog 如何自动将 DCG 语法转换为一组 Prolog 规则。

例如,我有以下 DCG 语法:

move --> step.
move --> step, move.

step --> [up].
step --> [down].

在哪里:

moove是可能的 moove 列表,而step是可以向上向下的单个移动

所以它说一个移动列表可以是一个单一的移动(一个步骤)或一个列表,一个由更多移动组成的列表,可以看作是一个单一的移动(一个步骤),然后是一个移动的列表(一个移动)。

所以这个语法可以生成如下列表的短语:[up, down, down, up, down] 或 like: [up]

这很简单

然后他展示了 Prolog 如何自动将之前的 DCG 语法转换成一套标准的 Prolog 规则(我之所以把它重命名为 move2 和 step2 只是因为我把这段代码放在了之前的 DCG 语法的同一个文件中):

/* move2 it is TRUE if the difference from the lists List and Rest is an
   acceptable move.
*/

/* BASE CASE: A moves list can be a single move (a step that can be "up" or "down")
   It is TRUE that the difference from the lists List and Rest is an acceptable move
   if it is TRUE that the head of the list is an acceptable move
*/
move2(List, Rest) :- step2(List, Rest).

/* GENERAL CASE: A moves list can be a single move followed by a list of moves.
   The difference of List1 and Rest is a valid move if it is TRUE that:
   the difference between List1 and List 2 is a step
   the difference between List2 and Rest is a move
*/ 
move2(List1, Rest) :- step2(List1, List2),
                      move2(List2, Rest).

/* step predicate extract a single step ("up" or "down") from a list
*/
step2([up|Rest], Rest).

step2([down|Rest], Rest).

正如我在评论中所写的那样,我试图解释这些规则的含义,但我不太确定我的解释......

你能给我一些提示来很好地理解它吗?

肿瘤坏死因子

安德烈亚

4

1 回答 1

0

我认为代码或您的解释没有任何问题,尽管我认为您是“以声明方式”看待它而不将其视为 DCG。我可能会这样写代码:

step --> [up].
step --> [down].

move --> [].
move --> step, move.

这应该等效地工作,但它比你的更容易扩展和维护,因为它没有明确维护差异列表。

Prolog 越接近表达意图的自然语言越好。如果要花很多话来解释你的代码是如何工作的,那么你就是在按程序进行编程。上面的 Prolog 几乎是我们可以开箱即用的。我们可以通过创建一些助手来更进一步:

one_or_more(_, [])    --> [].
one_or_more(R, [V|Vs]) --> 
  { Rule =.. [R, V] }, 
  Rule, 
  one_or_more(R, Vs).

step(up)   --> [up].
step(down) --> [down].

moves(Steps) --> one_or_more(step, Steps).

(上面的代码未经测试。)重点是为了说明声明式编程的力量。编写一个类似的谓词可能需要更多的工作one_or_more//2,但是一旦你拥有它,你的程序的其余部分就会被提升为一种更具声明性的风格。一些评论可能是必要的,因为它是如何one_or_more//2工作的并不是很明显(如果它甚至可以工作)。上面的声明式阅读是,“move(Steps) 匹配一个或多个步骤”。这和我原来版本的声明式阅读和你的声明式阅读是一样的。不同之处在于每个代码都更接近于明显的声明式阅读。

于 2013-05-15T17:17:35.857 回答