Deleting a record in a different script

I’m using: SWI-Prolog version 8.0.3

I want the code to:
i have a lot of records like this: place(_ ,_ ,_ ,_ ,FT,_) in a script called nodes.pl, everyone in a different row… and i want to tell from another script: "if FT in place is > X then delete the entire row…

i want this function in the main script, but the “place-like” records are in another script called nodes.pl

The purpose is to delete from the nodes.pl database the people who have been in a place (whatever the place is) more then 30 days ago.
I have to do this operation at the starting of the program… so i can work only with “new” records…

i know there could be a lot of errors but i’m at my beginning with prolog and this is for a univ project and i don’t know how to figure this problem out…
i don’t think it is rocket science but i’m not so skilled so far

thanks a lot for your help!

PS. i want to iterate the function for every row in the file so i can work only with the recent people at every start.

My code looks like this:

%main.pl

%example of place element
%place("Eva", 1487273300000, 0, 0, 1594380400000, "Paris").
%place("Mark", 1575373400000, 0, 0, 1667383500000, "NY").
%place("Linda", 1511373700000, 0, 0, 1888380200000, "Rome").
%.....

  delete_from_nodes(place):- %place is in the nodes.pl script
    get_time(Curr),
    Limit is (Curr-2592000)*1000,   %30 days
    FT>Limit,   %FT is an element of place, that is in nodes.pl script
    retract(place(_,_,_,_,FT,_)).

This looks like it would be a file of facts place(_ ,_ ,_ ,_ ,FT,_). Is this correct?

If so then retract/1 will expect the facts to be loaded into the in-memory Prolog database using consult/1. The nodes.pl could also be a module in which case you could use use_module/1.

The one thing I have never attempted in the manner you have chosen is to save facts from the in-memory database back into a file as a snapshot of a clause. Normally for such I would use library(persistency) which can assert/retract/load and save facts. The result from library(persistency) is a journal of actions instead of a snapshot of a state of facts.

While not its typical use, I guess listing/1 could be used with the output captured to file using with_output_to/2, again something I don’t normally do.

HTH

yes nodes.pl is a file of facts that i can isert with an operation through the main.pl file.
what i want to do is check from the main.pl if there are some of “place(…)” that i want to eliminate

First, times in SWI-Prolog are in seconds (may be float), so I do not see the reason for the *1000. Second, FT>Limit will raise an error as FT is not known at the time of call. >/2 can only compare concrete values. To remove such clauses you may use this (untested, may have typos).

Limit is Curr-3600*24*30,
forall(( clause(place(_,_,_,_,FT,_), true, Ref),
         FT < Limit,    % must be before, no?
       ),
       erase(Ref)).

thank you too for the response… i’ll check the code… but what is clause? do i have to specify that i want to check in the nodes.pl file?

You need three steps, find a clause (row), check it is too old and remove it. There are two ways to do the last step. One is using clause/3 to get a handle on the clause and use erase/1 to erase it and the other is to get enough arguments to safely use retractall/3 to remove the clause. I’ve opted for the first.

This assumes nodes.pl is loaded in memory and the predicate place/6 is dynamic. See dynamic/1. Nothing is removed from nodes.pl. You could use listing/1 to create a new nodes.pl or, as @EricGT suggests, look at libraryt(persistency). May be a bit overwhelming :slight_smile:

See:
SWI-Prolog Glossary
StackOveflow answer

A Prolog predicate can have multiple clauses, e.g.

alpha([C|T],T) -->
    [C],
   { between(0x41,0x5A,C) }.
alpha([C|T],T) -->
    [C],
   { between(0x61,0x7A,C) }.

the formatting convention is to separate Prolog predicates with blank lines and to not separate clauses in a predicate.

A series of the facts with the same predicate indicator, e.g.

place("Eva", 1487273300000, 0, 0, 1594380400000, "Paris").
place("Mark", 1575373400000, 0, 0, 1667383500000, "NY").
place("Linda", 1511373700000, 0, 0, 1888380200000, "Rome").

are also clauses, but also known as facts.
Don’t worry it took me quite some time to get use to it. You did the correct thing by simply asking.


Based on the way you ask that you seem to be missing the concept that you have to load the facts in the file into memory before you can use the code on the facts.

Try doing some of the tutorials at Learn Prolog Now!. You will need to work up to and complete section 12 - Splitting Programs over Files

thank you all for your response!
i post my code here if you want to visualize it:

%main


%these are the other scripts 
:-[nodi].
:-[db].
:-[positivo].
:-[cf].
:-[predicati].
:-[parser].
:-[main_sanita].
:-[main_utente].


:-dynamic place/6.   %place is in nodi.pl that i inserted at the beginnig..

...
eliminadanodi(place):-
    get_time(Curr),
    Limit is (Curr-3600*24*30),
    forall(( clause(place(_,_,_,_,FT,_), true, Ref),
         FT < Limit),
       erase(Ref)).

can the program read from nodi.pl doing this?

You should put the code into a module and use use_module/1,2 instead.

i saw use_module/1 and 2 but the example use lists… i don’t understand how to replace in my case.

is it sufficient to write use_module(nodi) before the code?

1 Like

First lets get the terminology correct. When you say script I typically think Bash scripts. The word I would use is Prolog source code file.

The next item is that to use use_module/1,2 the Prolog source code file needs to be a proper module.

To convert a Prolog source code file into a module the first non comment line needs to be a Prolog directive (:-) using module/2,3 See: Defining a Module

When you note the example use lists I take it that you are referring to the second argument of module/2.
Making the list of predicates to export can be daunting the first time, but it can also be tedious once you understand it and the list is long. See: Build list of predicates that can be exported from a module
This will give you the full list from which you can just delete the predicates not needed. It is so much easier to delete unneeded predicates that get all of the needed predicates correct by typing them in by hand.

Once all of the Prolog source code files like :-[nodi]. are converted to Prolog modules, then you can just change the lines to something like

:- use_module(nodi).

HTH

thenak you very much for your patient :slight_smile: now it works properly… i thank you all for your explanations…

It was my pleasure. :grinning:

When people take the help and figure out details on their own it is much preferred to others who want it all spoon feed to them.