My use case for a non-optimized clause/2 is the extension of a meta-interpreter to functional programming. I do not know how to keep my extension to functional programming simple without the non-optimized clause/2.
Here is my extended meta-interpreter:
i( true ) :- true .
i( (Body1,Body2) ) :- i( Body1 ), i( Body2 ) .
i( Goal ) :-
\+ Goal = true ,
\+ Goal = (_,_) ,
rw_final(Goal,Head) , % applying all functions to Goal yields a rule Head!
clause(Head,Body) ,
i( Body ).
rw_final( Old , New ) :-
subst( Old, Zw ) , ! , % single nested function call
rw_final( Zw, New ). % more function calls
rw_final( Old , Old ) .
% subst(+Old, -New ) - apply any substition to a subtree of Old to get New
subst( Old , Old ) :- var(Old) , ! , fail . % abort for variables (no substitution)
subst( Old , Old ) :- atomic(Old) , ! , fail . % abort for integers and atoms (no substitution)
subst( Old , New ) :- Old =.. [F,A|As] , % i.e. Old = F(A,...)
substl( [F,A|As], Ns ) , % inner function calls first
New =.. Ns .
subst( Old , New ) :- ( Old ==> New if B ) , B . % apply functions and call the guard goal B
% substl( +L , -LwithSubst ) - apply subst to any element of L
substl( [A|As], [N|As] ) :- subst( A, N ) .
substl( [A|As], [A|Ns] ) :- substl( As, Ns ) .
Here are the operators needed to define functions:
:- op( 750 , xfx , ==> ) . % function operator ==>
:- op( 1180 , xfx , if ) . % function definition operator if
Here are the additions that allow to call a function and to return a function result with using the non-optimized clause/2 predicate.
X = Y ==> equal(X,Y) if true . % needed to mask '=' in i(Goal)
equal(X,X) . % needed to unify left-hand-side of '=' with function call result
Here are two example functions:
sqr(X) ==> X*X if true. % an example function
addlist( [ ] ) ==> 0 if true . % a list as argument
addlist([X|L]) ==> X + addlist(L) if true . % function using 2 clauses
Here is how I want to use the functions:
:- use_module(library(clpfd)).
go2(S,D,F) :- i( use_i(S,F) ) , % meta-interpreter yields: S=4*4 , F=3*3
D #= F , % assignment computes D = 9
ic(S,D) . % Prolog goal checks ?- ic(4*4,9)
% when called through meta-interpreter i(...)
use_i(S,F) :- % I want to get use_i(4*4,3*3)
S=sqr(4), F=sqr(3). % but I get use_i(sqr(4),sqr(3))
ic( 4*4 , 9 ) . % example Prolog fact
go5(L,R) :- i( use_5( L ) ) , % calling the meta-interpreter
R #= L . % evaluating term L and assigning result to R
% when called through meta-interpreter i(...)
use_5(L) :- % I want to get use_5( 3+0 )
L = addlist([3]) . % but I get use_5(addlist[3])
I would really like to continue working with my meta-interpreter extension to functional programming as this also supports, e.g., substituting function calls by their result, nested functions, higher-order functions, using deterministic predicates as functions - and all this works well with older SWI-Prolog versions that do NOT optimize clause/2.
I do not know whether there is an easy workaround to solve the problems shown in the example above. If not, I would appreciate to have a chance to use a non-optimized clause/2 command
in an actual version of SWI-Prolog.