Retracting and asserting to another file in Prolog

1.2k Views Asked by At

I'm trying to retract and assert a fact in another file. One (fruit1.pl) contains a couple of facts, and another (fruit.pl) contains a predicate start which designates which fact that another predicate insert_fruit will update:

fruit1.pl

fruit(apple, [[2, yellow], [1, brown]]).
fruit(orange, [[3, orange], [2, orange]]).

fruit.pl

:- dynamic fruit/2.

start :-
    consult('fruit1.pl'),
    File = 'fruit1.pl',
    Name = apple,
    Price = 2,
    Color = red,
    insert_fruit(File, Name, Price, Color). 

insert_fruit(File, Name, Price, Color) :-
   open(File, update, Stream),
   retract(fruit(Name, Information)),
   assert(fruit(Name, [[Price, Color]|Information])),
   close(Stream). 

However insert_fruit is not working as intended, as I believe it needs to include Stream to modify the other file, although I have no idea how (retract(Stream, ...) doesn't work). Is there some I would be able to get the retract and assert predicates to function in the other file?

1

There are 1 best solutions below

4
On BEST ANSWER

In SWI-Prolog you can assert/retract facts from a file that is used as a persistent fact store by using library persistency:

  1. You declare fruit/3 as persistent. Optionally: you annotate the arguments with a type for automatic type checking.
  2. You attach a file that will serve as the persistent fact store upon initialization of the fruit module (in this case fruit1.pl).
  3. You add predicates for inserting (i.e., add_fruit/3) and querying (i.e., current_fruit/3) fruity facts. Retraction is handled similarly.
  4. Notice that you can use the fact store in a multi-threaded environment by using with_mutex/2 (especially useful when you start retracting facts as well).

Code

:- module(
  fruit,
  [
    add_fruit/3, % +Name:atom, +Price:float, +Color:atom
    current_fruit/3 % ?Name:atom, ?Price:float, ?Color:atom
  ]
).

:- use_module(library(persistency)).

:- persistent(fruit(name:atom, price:float, color:atom)).

:- initialization(db_attach('fruit1.pl', [])).

add_fruit(Name, Price, Color):-
  with_mutex(fruit_db, assert_fruit(Name, Price, Color)).

current_fruit(Name, Price, Color):-
  with_mutex(fruit_db, fruit(Name, Price, Color)).

Illustration of use

Start Prolog, load fruit.pl, execute:

?- add_fruit(apple, 1.10, red).

Close Prolog, start Prolog (again), execute:

?- current_fruit(X, Y, Z).
X = apple,
Y = 1.1,
Z = red

You are now reading facts from fruit1.pl!

Illustration of automatic type checking

As mentioned before, the library also performs type checking for you, e.g.:

?- add_fruit(pear, expensive, green).
ERROR: Type error: `float' expected, found `expensive' (an atom)