we are currently working on the implementation of the predicate reduce, which Needs to take a list L, a binary function F that operates on the elements of L and has neutral element N and maps them to a number E that is obtained by applying F to the elements of L recursively.
Here's our Code so far:
reduce([],F,NEUTRAL,EE).
reduce([H|T],F,NEUTRAL,EE) :-
Goal =.. [F, H, NEUTRAL, EE],
call(Goal),
reduce(T,F,NEUTRAL,EE).
add(N1,NEUTRAL, EE) :- EE is EE + N1 + NEUTRAL.
mult(N1,NEUTRAL, EE) :- EE is N1 * EE * NEUTRAL.
the Problem is: to same sample queries such as ?- reduce([], add, 0, R). we just get a boolean (in this case true), to others an error back, which tells us that our Arguments are not properly instantiated. What we actually aim for is a Response like R = 0. (for the example given above).
Hope you can help us, please do not be too complicated as we are Prolog beginners ;)
You need the neutral element to end the recursion. You don't need it at every step. I'd almost say that the neutral element belongs with the operator, not with the reduce. Something like this:
Then, your
reducecould look like this:But let's keep it easy for now and do it as suggested in the question. You need the neutral element only if the list of operands is empty, to set your result:
Otherwise, go in the recursion and then apply the operation to the result (and you can use
calldirectly):You can see here how to use
reduce/4for example withappend/3.Do you see
Ninsidecall? I do not see it, and it doesn't belong there.For completeness, the two operators:
There is no mention of a neutral element either.
By the way: what you have called "reduce" is also known as a "fold" over a list. You could define your
reduce/3in terms offoldllike this:The recursion and the
callboth happen insidefoldl, you don't needreduce/4at all.How would you solve this in a procedural language? Using pseudo-code with a C-like syntax, and assuming we have some support for generics, it could go like this:
(apparently if this was indeed C++ we would be using iterators, not an index...)
It is not at all that different from the Prolog version. And if you did it the same way as the
foldlabove, it would probably look like this:Again, no mention of the neutral element inside the loop, nor in the call to
op().