【问题标题】:Some doubts about how Prolog automatically convert DCG grammars int a set of rules关于Prolog如何自动将DCG语法转换成一组规则的一些疑惑
【发布时间】:2013-05-15 16:03:39
【问题描述】:

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

例如我有以下DCG语法:

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

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

地点:

moove 是一个可能的moves 列表,step 是一个可以updown 的单一动作

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

所以这个语法可以生成如下列表的短语:[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).

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

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

Tnx

安德烈亚

【问题讨论】:

    标签: prolog dcg


    【解决方案1】:

    我认为代码或您的解释没有任何问题,尽管我认为您是“以声明方式”查看它而不将其视为 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 周围可能需要一些 cmets,因为它的工作原理并不是很明显如果 它甚至可以工作)。上面的声明式阅读是,“move(Steps) 匹配一个或多个步骤”。这和我原来版本的声明式阅读和你的声明式阅读是一样的。不同之处在于每个代码都更接近于明显的声明式阅读。

    【讨论】:

    • 您的move//0 不等同于OP 发布的内容,因为它也接受空列表,但OP 的定义不接受。还应将one_or_more//2 称为zero_or_more//2 以反映这一点。
    • mmm 我对这行代码有些疑问: Rule =.. [R, V] What is =.. ?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 2012-01-29
    • 1970-01-01
    相关资源
    最近更新 更多