我正在运行Prolog并尝试编写一个返回列表长度的小函数:
len([],0).
len([XS], Y) :-
len([X|XS], M),
Y is M+1.
我的逻辑是递归调用应包括列表尾部(XS)并将前一长度增加1(Y为M + 1。)
这总是返回false。
有什么想法吗?
答案 0 :(得分:4)
以下是调试和测试Prolog谓词的一般方法:
想一想:在Prolog中,您不需要编写一些测试数据。你根本不需要理解一个谓词:只需提交自由变量!这总是一个专业的举动!
所以在你的情况下,那是
?- len(L,N).
L = [],
N = 0 ;
*LOOPS**
你的定义并不像你声称的那样糟糕:至少,空列表是正确的。
现在,请查看您可能收到的编译器警告:
Warning: user://1:11:
Singleton variables: [X]
接下来,从箭头:-
的方向读取递归规则,即从右到左:
如果len([X|Xs], M)
为真且Y is M+1
为真,如果一切正确,我们可以得出结论
len([XS], Y)
也是如此。所以你总是总结一下长度为1的列表([Xs]
)。
您需要将其重新制定为len([X|Xs], M) :- len(Xs, N), Y is M+1
。
这是另一种策略:
通过删除目标,我们可以推广一个程序 1 。这是我最喜欢的方式。通过像这样添加谓词(*)/1
:
:- op(950,fy, *).
*_.
现在,让我们从你的程序中删除所有目标:
len([],0). len([XS], Y) :- *len([X|XS], M), *Y is M+1.
我们现在所拥有的是一种概括。我们将再次查看最常见查询的答案:
?- len(L, N).
L = [],
N = 0 ;
L = [_].
什么? len/2
仅适用于长度为0和1的列表。这意味着,即使len([1,2], N)
也会失败!所以现在我们确切地知道:必须修复程序剩余部分中的某些内容。实际上,[XS]
只描述了长度为1的列表。所以必须将其删除......
精美印刷:
1适用某些限制。从本质上讲,你的程序必须是一个纯粹的,单调的程序。