1

I want to retract fact, but I have not direct access to the name of fact. To get anything from this fact I'd use following code:

facts.pl file:

:- dynamic fact/2.

fact(a, b).
fact(b, e). 
fact(a, c). 
fact(e, d). 
fact(c, d). 
fact(d, f). 
fact(d, g).

solution.pl file:

someProcedure(StructureName) :-
    call(StructureName, a, X).

Now how could I retract that dynamic fact from memory in solution.pl?

I've tried something like:

deleteProcedure(StructName, A, B) :-
    retract(call(StructName, A, B)).

But I get error:

ERROR: retract/1: No permission to modify static procedure `call/3'
ERROR: Defined at /usr/lib/swi-prolog/boot/init.pl:217
Temax
  • 87
  • 7
  • 1
    You've got a point. But you need to resort to pedestrian means using `(=..)/2` or `functor/3` and `arg/3` today. – false Dec 01 '22 at 14:59

1 Answers1

3

You can use the univ predicate (=../2) to build the term to retract.

retract_fact(Name, A, B) :-
  Fact =.. [Name,A,B],
  retract(Fact).

Note this solution accepts only atoms as the Name, so it is tailored to your example:

?- retract_fact(fact,a,b).
true.

and will not work if you pass a compound term, e.g.:

:- dynamic fact/3.
fact(a, b, c).

?- retract_fact(fact(a),b,c).
ERROR: Type error: `atom' expected, found `fact(a)' (a compound)

Here is a revised solution accepting compound terms:

retract_fact(Term, A, B) :-
  Term =.. L,
  append(L, [A,B], L1),
  Fact =.. L1,
  retract(Fact).

Sample run:

?- retract_fact(fact(a),b,c).
true.

?- retract_fact(fact,b,e).
true.
repeat
  • 18,496
  • 4
  • 54
  • 166
gusbro
  • 22,357
  • 35
  • 46