我刚刚开始学习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件小事:
CCount is L0+1, WCount is A0+1
等如何成为有效的语法? L0
和A0
完全未定义。 Prolog如何知道例如A0+1
是什么?不应该是A0 is WCount + 1
吗?
我并不完全明白stringCounter([H|[]],1,1) :- char_type(H, alpha),!.
和stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).
的目的是什么。
如果我将stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).
从底部(向上)移开,为什么函数的结果会发生变化?我试过了,移动那条线后得到了完全不同的结果。
对于非常基本/愚蠢的问题感到抱歉,但我很难将我的头脑包裹在Prolog和逻辑编程中。
答案 0 :(得分:2)
函数任务是计算字符串中有多少个字符以及有多少字(据我所知)。
否CCount
(第二个参数)与alpha
个字符的数量统一,WCount
与alpha
个字符的序列数统一。 Soo 'foo8bar_qux'
与CCount=9
和WCount=3
结合使用。
是吗?我们看到,该行上方有一行:
CCount is L0+1
,WCount is A0+1
等是如何有效的语法?L0
和A0
完全未定义。 (..)
stringCounter(T,L0,A0),
所以最多stringCounter
接地L0
和A0
。如果L0
和A0
在stringCounter/3
调用后接地是不变的,那么它将正常工作。你是正确的,Prolog无法处理is/2
谓词的未接地变量。
我并不完全明白
stringCounter([H|[]],1,1) :- char_type(H, alpha),!.
和stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).
的目的是什么。
[H|[]]
是[H]
的详细形式:包含一个元素[H]
的列表。在这里,我们检查H
是否是字母字符。如果是,则我们将其视为一个(CCount
和WCount
)。请注意,它以 cut (!
)结尾。这意味着忽略其他子句。
声明stringCounter([_|T],CCount,WCount):- !, stringCounter(T,CCount,WCount).
是最后一个。由于其他子句使用cut,这意味着只有在列表包含至少一个元素且该元素不是alpha
时才会触发此子句。在这种情况下,我们在尾部进行递归调用,不计算字符(对于b CCount
和WCount
。
如果我将
stringCounter([_|T],CCount,WCount) :- !, stringCounter(T,CCount,WCount).
从底部(向上)移开,为什么函数的结果会发生变化?我试过了,在移动那条线之后我得到了完全不同的结果。
因为如前所述,stringCounter([_|T],CCount,WCount)
头与每个非空列表匹配。只是因为上面的条款被削减,它才被隐含地保护,只接受非alpha字符等。
所以万一你把它移到了顶部。它可能会导致所有字符串都有CCount=0
和WCount=0
,因为它将递归枚举字符串直到它到达结尾,在这种情况下它将与基类stringCounter([],0,0)
统一。 Cut可以使程序更有效,但是由于一个子句的规范对该子句下面的条款有影响,它们使程序不易理解。