我有以下代码用于在Prolog中获取列表的长度,它使用递归方式实现。
是否有其他获取长度的方法?
len([], 0).
len([H|T], N) :-
len(T, NT), N is NT + 1.
任何建议都将不胜感激。
len([], 0).
len([H|T], N) :-
len(T, NT), N is NT + 1.
任何建议都将不胜感激。
length/2
。它是如何实现的并不重要--更重要的是它的语义:?- length([a,b], 2).
true.
?- length([a,b], 4).
false.
?- length([a,b,c], Len).
Len = 3.
?- length(List, 3).
List = [_G937, _G940, _G943].
?- length(List, Len).
List = [],
Len = 0 ;
List = [_G949],
Len = 1 ;
List = [_G949, _G952],
Len = 2 . % and so on
length/2
更简单的方式来查找列表的长度、检查列表的长度、创建指定长度的列表或枚举递增长度的列表。length/2
和其他漂亮的声明式内置函数。
重复一个元素N次
将列表分成一些长度的片段
列表中恰好有一对
旋转一个列表
我相信你能想到许多其他使用 length/2
的方法。
repeat/0
谓词的迭代解决方案,具体如下:getlength(L,N) :-
retractall(getlength_res(_)),
assert(getlength_res(0)),
retractall(getlength_list(_)),
assert(getlength_list(L)),
repeat,
(
getlength_list([]), !, getlength_res(N)
;
retract(getlength_res(V)), W is V + 1, assert(getlength_res(W)),
retract(getlength_list([_|T])), assert(getlength_list(T)), fail
).
repeat/0
迭代中使旧数字增加一。从某种意义上说,这两个动态维护的事实的行为非常像命令式语言中可分配的变量。
通常情况下,在Prolog中,迭代的解决方案比递归的解决方案难以阅读。考虑到任何具有类似于命令式编程语言赋值语句效果的东西都与Prolog的设计哲学不符,这应该不足为奇。assert
和retract
。不过,我确实喜欢这个答案,因为它展示了Prolog的这一方面。 - lurker抱歉,我忍不住要尝试这个“挑战”:
Input=[a,b,b,b,b,b,b,b,b,a,b,c,d,f], between(1,inf,K),findall( _,between(1,K,_),FreeList), ( FreeList=Input,!,true).
findall/3正在执行后台递归,代码正在对列表FreeList和Input进行统一,直到它们统一为止。
length(List, N)
。 :) 为什么需要它是非递归的? - lurkerappend
、maplist
或length
。它们在特定的Prolog实现中可能会被递归地编写,也可能不会。递归对于遍历列表中所有元素是必要的。如果你只想要第一个元素,可以像这样做:[H|T]=List
,它会获取头(第一个)元素H
或尾部列表T
。 - lurker