As a non-functional property the sharing is
observable. You can try the following:
p(A, B, C, D, E) :-
D = f(E,E,E,E),
C = f(D,D,D,D),
B = f(C,C,C,C),
A = f(B,B,B,B).
If you do a Logtalk source transformation
you get a clause of size 4^4+4^3+4^2+4^1 = 340
memory cells. If you don’t do a Logtalk source
transformation you get a clause of size 5*4 = 20
memory cells.
Same for the runtime, i.e. the thread time use
by calling for example:
?- p(Y, _, _, _, X).
I didn’t test yet, since I don’t have a souce
transformer. Maybe I can add some timing comparison
by using a manual transformation. This is observable
if the Prolog system doesn’t apply some common
subexpression elimination while compiling clauses.
Common subexpressions elimination would possibly
need hash calculation and 340 head searches, and
would slow down assert and retract, so I don’t
have this. Thats why I call it explicit sharing.
Its not an automatism. Its something that the
programmer can do by using (=)/2.
A modified Logtalk transformation could possibly
only move the terms to the head up to some depth.
But to not negatively affect deep indexing it
would need some good heuristics here. This is
not yet a problem in my Prolog system, since I
don’t have yet deep indexing.
Edit 02.01.2019:
Here are some timings, pretty much the ratio
340 cell/20 cell from slow to fast:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.16)
/* with sharing */
?- time((between(1,1000000,_),p(Y,_,_,_,X),fail;true)).
% 1,999,999 inferences, 0.266 CPU in 0.254 seconds (104% CPU, 7529408 Lips)
true.
/* without sharing */
?- time((between(1,1000000,_),p2(Y,_,_,_,X),fail;true)).
% 1,999,999 inferences, 3.297 CPU in 3.289 seconds (100% CPU, 606635 Lips)
true.
I used the following manually transformed p/5:
?- listing(p2/5).
p2(f(f(f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A))), f(f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A))), f(f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A))), f(f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)))), f(f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A))), f(f(A, A, A, A), f(A, A, A, A), f(A, A, A, A),
f(A, A, A, A)), f(A, A, A, A), A).