How to delete all records in a database using 'The recorded database' predicates?

Hello everyone.
I was practicing the recorded database predicates (recorda, recorded, erase) when I realized that it’s not possible on the first try to delete all records at once from a database. Recorda/3 returns a different reference for each term registered and erase/1 only accepts one reference at a time. How could I delete all the records or delete the whole database?

My objective is avoiding the use of dynamic predicates as assert/1 or retractall/1 to reduce the time cost of my code. I give you my code below to show you the format of the terms I want to save:

add_vertex(Vertex,Rgb, Ref):- recorda(vertices_graph, [Vertex, Rgb], Ref).

consult_vertex(Vertex,Rgb):- recorded(vertices_graph, [Vertex, Rgb]).

I hope you can help me. :call_me_hand:t2:

Using forall(recorded(Key, _, Ref), erase(Ref)) is as good as it gets. For some operations the recorded db is indeed faster, but for others it is not. Notably in your example it is likely to loose from the dynamic database on lookup if there is are more than a trivial number of vertices. The recorded database is old school …

I’d first try using the dynamic db. For max scalability and indexing try to avoid compound terms in the facts. If that performs worse than you hoped, come back here with what you did and if possible with something we can reproduce.

2 Likes

In looking for an answer for the question yesterday by scanning the SWI-Prolog code for erase ran across several examples of the code segment you noted.

However, also noticed a use related to tabling.

Can you enlighten us on details of how tabling uses the code and if there are reasons not to use tabling for problems as noted by the OP?

I did a git grep, but I do not see any use of the recorded database in the tabling code. Only in the tests, maintaining toplevel variable bindings ($Var) and it library(gensym). For toplevel variables they have one interesting property: they can store any term, i.e., holding cycles, sharing subterms, attributes, etc. The dynamic db cannot hold neither cycles, nor attributed variables. Terms with sharing subterms are blown up by the standard assertz/1.

For gensym/2 it is probably mostly history, but there may also be some advantage as it concerns few records that may be frequently updated. SWI-Prolog’s dynamic predicates can sometimes cause slowdowns for predicates holding one or a few clauses that are very frequently updated.

The the C code you find PL_record(). The name comes from the recorded database and the recorded database uses these primitives, but otherwise it is a different story. PL_record() takes a Prolog term and stores it in a permanent (malloc’ed) place. It simply returns a pointer to its location. C code can use this to store terms in memory that must survive backtracking and/or be usable from different C contexts. Note that the term_t handles that reference Prolog terms are scoped to the current foreign predicate execution, so you cannot store and reuse them.

1 Like

Thanks.

That will probably take me a few months or more to digest and fully understand. :slightly_smiling_face: