Many Prolog systems don't allow user defined evaluable predicates.
Sometimes the problem is that the evaluable predicates live in
another namespace. Sometimes the Prolog system shyes away from jumping back into Prolog execution while doing an arithmetic evaluation in the host language.
Some Prolog systems have nevertheless user defined evaluable predicates, like ECLiPSe Prolog and Jekejeke Prolog. In Jekejeke Prolog the overhead was two fold. To my surprise in the new Dogelog runtime user definable evaluable
predicates show an advantage:
/* Dogelog Runtime 0.9.5 */
fact(0, 1) :- !.
fact(N, X) :- M is N-1, fact(M, Y), X is Y*N.
fact2(0, 1) :- !.
fact2(N, X) :- X is fact2(N-1)*N.
for(_).
for(N) :- N > 1, M is N - 1, for(M).
% ?- time((for(1000), fact(1000, _), fail; true)).
% % Wall 1595 ms, trim 0 ms
% ?- time((for(1000), _ is fact2(1000), fail; true)).
% % Wall 1394 ms, trim 0 ms
I am attributing the slight speed advantage to the more concise formulation in fact2/2. The formulation uses less Prolog logical variables. And the user defined evaluable predicates capable (is)/2
internally does also no Prolog logical variables, the host language assigments that happen do not allocate
a Prolog logical variable or trail the same, so that in the end there is a speed-up.