问题
I'm writing a tokeniser and I want to use if_/3 to preserve logical-purity in my code.
The code looks like the following code1 on the left—but I want it to look like the one on the right.
if_(Cond1_1, % ( Cond1_1 Then1, % *=> Then1 if_(Cond2_1, % ; Cond2_1 Then2, % *=> Then2 if_(Cond3_1, % ; Cond3_1 Then3, % *=> Then3 if_(Cond4_1, % ; Cond4_1 Then4, % *=> Then4 if_(Cond5_1, % ; Cond5_1 Then5, % *=> Then5 Else5 % ; Else5 ) ) ) ) ). % ).
To do the rewriting of (*=>)/2
to if_/3
in SWI-Prolog I came up with:
:- op(1050,xfy,*=>). :- multifile goal_expansion/2. goal_expansion((Cond *=> Then ; Else), if_(Cond,Then,Else)). goal_expansion( Cond *=> Then , (call(Cond,true), call(Then))).
"Done," I thought...
But I became doubtful after reading the SWI-Prolog documentation for goal_expansion/2:
Only goals appearing in the body of clauses when reading a source file are expanded using this mechanism, and only if they appear literally in the clause, or as an argument to a defined meta-predicate that is annotated using `0' (see meta_predicate/1). Other cases need a real predicate definition.
So here's my actual question: Do I need a real predicate definition, too?
Footnote 1: The actual code has an even longer chain of else if
s.
回答1:
You need a if_/3 predicate definition, to at least assign it a meta predicate declaration, otherwise expansion will stop, if there is no meta predicate declaration for if_/3 itself.
You can try yourself, I am using only this expansion:
:- op(1050,xfy,*=>).
:- multifile goal_expansion/2.
goal_expansion((Cond *=> Then ; Else), if_(Cond,Then,Else)).
Without meta predicate declaration:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)
?- expand_goal((a *=> b; c *=> d; e), X).
X = if_(a, b, (c*=>d;e)).
With meta predicate declaration:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)
:- meta_predicate if_(1,0,0).
?- expand_goal((a *=> b; c *=> d; e), X).
X = if_(a, b, if_(c, d, e)).
This is same behaviour in SWI-Prolog and Jekejeke Prolog. You could study the source code to better understand why the meta predicate declaration is needed.
See for example here:
https://github.com/jburse/jekejeke-devel/blob/master/jekrun/headless/jekpro/frequent/standard/expand.p#L220
来源:https://stackoverflow.com/questions/55404139/goal-expansion-for-an-if-3-operator-in-prolog