I’m currently trying to create an EBG using SWI-Prolog, however, copy_term/2 is not working properly as it should in the ISO Standard.
When i try to copy something like:
copy_term( (n_queens( GenQueens, GenSolution ), GenBody ), ( n_queens( [1, 2, 3, 4], Solution ), ( perm( [1, 2, 3, 4], P ), safe( P ))).
It succeeds but GenBody is not a copy of ( perm( [1, 2, 3, 4], P ), safe( P ) ) because GenBody is a variable and copy-term/2 is not relational.
How can i work around this?
Try switching sides, copy_term/2 has mode (+,-):
?- copy_term( ( n_queens( [1, 2, 3, 4], Solution ),
( perm( [1, 2, 3, 4], P ), safe( P ))),
(n_queens( GenQueens, GenSolution ),
GenBody )).
GenQueens = [1, 2, 3, 4],
GenBody = (perm([1, 2, 3, 4], _A), safe(_A)).
This is not a solution, because in EBG, GenBody’s perm list neither GenQueens should be instantiated. copy_term/2 should be relational. In EBG we always want to do copy_term((GenGoal :- GenBody), (Goal :- Body)), not the other way around.
Do you mean bi-directional? Thats impossible, copy_term/2 is defined as:
% The purpose of duplicate/2 is to get a new copy of
% an expression with all new variables.
duplicate(Old, New) :- assert('$marker'(Old)),
retract('$marker'(Copy)),
New = Copy. % for steadfastness
It won’t touch Old
unless New
contains some variables of Old
.
See also here:
https://www.cs.unm.edu/~luger/ai-final/code/PROLOG.ebg.html
You’re right, however, in the ISO Standard, copy_term/2 is relational, and in GNU Prolog it also is:
This important because we want it to copy both ways. SWI-Prolog implementation is most-likely wrong.
I’m truly very sorry, i was using clause(Goal, Body) instead of clause(GenGoal, GenBody)
Sorry for wasting your time! Your implementation is correct 