关于Prolog如何在一组规则中自动转换DCG语法的一些疑问

关于Prolog如何在一组规则中自动转换DCG语法的一些疑问,prolog,dcg,Prolog,Dcg,我正在用Ivan Bratko的书《人工智能编程》学习Prolog中的DCG语法,我发现了一些问题来理解Prolog如何自动将DCG语法转换成一组Prolog规则 例如,我有以下DCG语法: move --> step. move --> step, move. step --> [up]. step --> [down]. /* move2 it is TRUE if the difference from the lists List and Rest is an

我正在用Ivan Bratko的书《人工智能编程》学习Prolog中的DCG语法,我发现了一些问题来理解Prolog如何自动将DCG语法转换成一组Prolog规则

例如,我有以下DCG语法:

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

step --> [up].
step --> [down].
/* 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).
其中:

moove是一个可能的moove列表,step是一个单独的动作,可以是向上向下

所以它说一个移动列表可以是一个移动列表(一步),也可以是一个由多个移动组成的列表,可以被看作是一个移动列表(一步),然后是一个移动列表(一步)

因此,该语法可以生成如下列表所示的短语:[up,down,down,up,down]或类似:[up]

这很简单

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

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

你能给我一些提示让我更好地理解它吗

Tnx


Andrea

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

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

move --> [].
move --> step, move.
这应该是等效的,但是它比您的更容易扩展和维护,因为它没有显式地维护差异列表

你的序言越接近你意图的自然语言表达,就越好。如果要用很多词来解释代码是如何工作的,那么您就是在按程序编程。上面的序言差不多是我们能从盒子里拿出来的。我们可以进一步创建一些助手:

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\u或\u more//2
)可能需要更多的工作,但一旦有了它,程序的其余部分将提升为更具声明性的样式。对于
一个或多个//2
,可能需要一些注释,因为它的工作原理(如果它工作的话)并不明显。上面的声明性阅读是“移动(步骤)匹配一个或多个步骤”。这与我的原始版本的声明性阅读和你的声明性阅读相同。不同之处在于,每个的代码更接近于明显的声明性阅读。

您的
move//0
不等同于OP发布的内容,因为它也接受空列表,但OP的定义不接受。另外,应该调用
one_或_more//2
来反映这一点。mmm我对这一行代码有一些疑问:规则=。。什么是?