有些人怀疑Prolog如何在一组规则中自动转换DCG语法

时间:2013-05-15 16:03:40

标签: prolog dcg

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

例如,我有以下DCG语法:

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

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

其中:

moove 是可能的列表,步骤是一个单一的行动,可以向上向下

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

所以这个语法可以生成如下列表的短语:[上,下,下,上,下]或类似:[上]

这很简单

然后他展示了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).

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

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

TNX

安德烈

1 个答案:

答案 0 :(得分: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附近可能需要一些注释,因为它并不是很明显 它是如何工作的(如果它甚至可以工作)。对上述内容的声明性解读是“移动(步骤)与一个或多个步骤相匹配”。这与我的原始版本的声明性阅读以及对您的声明性阅读相同。不同之处在于每个代码更接近明显的声明性读数。