Reputation: 19
My code does perfect with numbers, but error with single quotation. I'm trying to write a foldl
function. When i do foldl1(concat, ['a','b'], X)
, it reports like "ERROR: Arithmetic: 'ab/0' is not a function".
what is the problem? prolog does not allow using is
with string?
foldl1(P, [H], X) :-
X is H.
foldl1(P, [H|T], X) :-
foldl1(P, T, Y),
call(P, H, Y, Z),
X is Z.
Upvotes: 1
Views: 119
Reputation: 60014
is/2 evaluates the arithmetic expression to the right, and unifies the result with the term to the left. Unification is also performed against the head' arguments, so you can write a simplified foldl1/3 like
foldl1(_, [H], H).
foldl1(P, [H|T], Z) :-
foldl1(P, T, Y),
call(P, H, Y, Z).
test:
?- foldl1(plus,[1,2,3],R).
R = 6 ;
false.
?- foldl1(concat,[1,2,3],R).
R = '123' ;
false.
I would place a cut after the recursion base, since [H]
and [H|T]
where T=[]
overlap, to avoid any last call - that would anyway fail - on eventual backtracking, like the redo induced by me, inputting ;
after the expected first answer while the interpreter waits for my choices.
After the cut (hope you can easily spot where to place it) we get:
?- foldl1(plus,[1,2,3],R).
R = 6.
?- foldl1(concat,[1,2,3],R).
R = '123'.
Now the interpreter 'knows' there are no more answers after the first...
Upvotes: 2
Reputation: 18663
It's also possible to implement a foldl1/3
predicate using first-argument indexing to avoid spurious choice-points without cuts and that is also tail-recursive. From the Logtalk library meta
object:
:- 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).
Sample calls:
?- meta::foldl1(plus,[1,2,3],R).
R = 6.
?- meta::foldl1(concat,[1,2,3],R).
R = '123'.
Upvotes: 1