2017-09-25 77 views
2

我刚刚开始学习Prolog的,我发现一些代码,我也很难理解:序言 - 新来的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).从底部(向上)移开,函数的结果会发生变化?我尝试过,并且在移动该行后得到了完全不同的结果。

对不起,基本的/愚蠢的问题,但我真的很难包装我的头围绕Prolog和逻辑编程。

回答

2

函数的任务是计算字符串中有多少个字符,以及有多少字(据我了解)。

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

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

他们是?上面这条线一号线,我们可以看到:

stringCounter(T,L0,A0), 

所以它是由stringCounter接地L0A0。如果在stringCounter/3调用后L0A0停止接地,那么它会正常工作。你是正确的,Prolog不能用is/2谓词处理不相关的变量。

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

[H|[]][H]冗长形式:用一种元素[H]列表。在这里,我们检查H是否是字母字符。如果是,那么我们把它算作一个(对于CCountWCount)。请注意,它以剪辑!)结束。这意味着其他子句被忽略。

该语句stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).是最后一个。由于其他子句使用剪切,这意味着该子句仅在列表包含至少一个元素的情况下触发,并且该元素不是alpha。在这种情况下,我们就尾递归调用,并且不计的字符(bouth CCountWCount

为什么功能变化的结果,如果我移动stringCounter([_|T],CCount,WCount) :- !, stringCounter(T,CCount,WCount).远离底部(向上)?我尝试了,我得到了一个完全不同的结果后,我搬到了该行。

因为在此之前正如所说,stringCounter([_|T],CCount,WCount)头与每一个非空列表相匹配。这是因为在条款裁员的唯一在那之上,它被隐含地保护只接受非alpha字符,等等。

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