我的代码非常适合数字,但单引号错误。我正在尝试编写一个foldl
函数。当我做foldl1(concat, ['a','b'], X)
时,它报告类似"ERROR: Arithmetic: 'ab/0' is not a function".
的问题是什么? Prolog不允许将is
与字符串一起使用?
foldl1(P, [H], X) :-
X is H.
foldl1(P, [H|T], X) :-
foldl1(P, T, Y),
call(P, H, Y, Z),
X is Z.
答案 0 :(得分:2)
is / 2在右边计算算术表达式,在将结果与左边的项统一。还针对 head '参数执行统一,因此您可以编写简化的foldl1 / 3像
foldl1(_, [H], H).
foldl1(P, [H|T], Z) :-
foldl1(P, T, Y),
call(P, H, Y, Z).
测试:
?- foldl1(plus,[1,2,3],R).
R = 6 ;
false.
?- foldl1(concat,[1,2,3],R).
R = '123' ;
false.
由于[H]
和[H|T]
在T=[]
重叠的地方,我会在递归基数之后放置一个切口,以避免在最终回溯时(例如,重做由我引起,在解释器等待我的选择时,在预期的第一个答案后输入;
。
切割后(希望您可以轻松地发现它的放置位置),我们得到:
?- foldl1(plus,[1,2,3],R).
R = 6.
?- foldl1(concat,[1,2,3],R).
R = '123'.
现在,口译员“知道”在第一个……之后没有更多答案了。
答案 1 :(得分:1)
也有可能使用第一参数索引来实现foldl1/3
谓词,以避免不切分的虚假选择点,并且这也是尾递归的。从Logtalk库meta
对象中:
:- meta_predicate(foldl1(3, *, *)).
foldl1(Closure, [Head| Tail], Result) :-
fold_left_(Tail, Closure, Head, Result).
fold_left_([], _, Result, Result).
fold_left_([Arg| Args], Closure, Acc, Result) :-
call(Closure, Acc, Arg, Acc2),
fold_left_(Args, Closure, Acc2, Result).
通话示例:
?- meta::foldl1(plus,[1,2,3],R).
R = 6.
?- meta::foldl1(concat,[1,2,3],R).
R = '123'.