Prolog - Prolog的新手,很难理解代码片段

时间:2017-09-25 13:28:48

标签: string recursion prolog increment

我刚刚开始学习Prolog,我找到了一些我很难理解的代码:

stringCounter([],0,0).
stringCounter([H|[]],1,1) :- char_type(H, alpha),!.
stringCounter([H1,H2|T],CCount,WCount):-
        char_type(H1, alpha),
        \+char_type(H2,alpha),
        !,
        stringCounter(T,L0,A0),
        CCount is L0+1, WCount is A0+1.

stringCounter([H|T],CCount,WCount):-
        char_type(H, alpha),
        !,
        stringCounter(T,L1,A1),
        CCount is L1+1, WCount is A1+0.

stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).

函数任务是计算字符串中有多少个字符以及有多少字(据我所知)。

我理解这里的大部分代码除了3件小事:

  1. CCount is L0+1, WCount is A0+1等如何成为有效的语法? L0A0完全未定义。 Prolog如何知道例如A0+1是什么?不应该是A0 is WCount + 1吗?

  2. 我并不完全明白stringCounter([H|[]],1,1) :- char_type(H, alpha),!.stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).的目的是什么。

  3. 如果我将stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).从底部(向上)移开,为什么函数的结果会发生变化?我试过了,移动那条线后得到了完全不同的结果。

  4. 对于非常基本/愚蠢的问题感到抱歉,但我很难将我的头脑包裹在Prolog和逻辑编程中。

1 个答案:

答案 0 :(得分:2)

  

函数任务是计算字符串中有多少个字符以及有多少字(据我所知)。

CCount(第二个参数)与alpha个字符的数量统一,WCountalpha个字符的序列数统一。 Soo 'foo8bar_qux'CCount=9WCount=3结合使用。

  

CCount is L0+1WCount is A0+1等是如何有效的语法? L0A0完全未定义。 (..)

是吗?我们看到,该行上方有一行:

stringCounter(T,L0,A0),

所以最多stringCounter接地L0A0。如果L0A0stringCounter/3调用后接地是不变的,那么它将正常工作。你是正确的,Prolog无法处理is/2谓词的未接地变量。

  

我并不完全明白stringCounter([H|[]],1,1) :- char_type(H, alpha),!.stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).的目的是什么。

[H|[]][H]的详细形式:包含一个元素[H]的列表。在这里,我们检查H是否是字母字符。如果是,则我们将其视为一个(CCountWCount)。请注意,它以 cut !)结尾。这意味着忽略其他子句。

声明stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).是最后一个。由于其他子句使用cut,这意味着只有在列表包含至少一个元素且该元素不是alpha时才会触发此子句。在这种情况下,我们在尾部进行递归调用,不计算字符(对于b CCountWCount

  

如果我将stringCounter([_|T],CCount,WCount) :- !, stringCounter(T,CCount,WCount).从底部(向上)移开,为什么函数的结果会发生变化?我试过了,在移动那条线之后我得到了完全不同的结果。

因为如前所述,stringCounter([_|T],CCount,WCount)头与每个非空列表匹配。只是因为上面的条款被削减,它才被隐含地保护,只接受非alpha字符等。

所以万一你把它移到了顶部。它可能会导致所有字符串都有CCount=0WCount=0,因为它将递归枚举字符串直到它到达结尾,在这种情况下它将与基类stringCounter([],0,0)统一。 Cut可以使程序更有效,但是由于一个子句的规范对该子句下面的条款有影响,它们使程序不易理解。