How to persist custom or non trivial data types in swi-prolog with persistency library?

Hello, I’ve made an Stackoverflow question (https://stackoverflow.com/questions/68297234/how-to-persist-custom-or-non-trivial-data-types-in-swi-prolog-with-persistency-l) about how to enable persistency to date type datas.

Rewriting the question here (for somebody that can help me):

I have a module file with something like this:

:- module(model,
          [ campament/5
          ]).

:- use_module(library(persistency)).

:- persistent
   campament(name:atom, date_from:date, date_to:date, ubication:text, description:text).

This definition is related to date data type (SWI-Prolog -- Dealing with time and date), that is not present in error library mentioned in persistent/1.

So, when I try to persist this clause I get an error:

?- use_module(model).

?- model:bd('data.db').

?- parse_time('20180720', iso_8601, From),
|  parse_time('20180729', iso_8601, To),
|  model:assert_campament('My campament', From, To, 'there', 'nothing').

ERROR: type `date' does not exist
ERROR: In:
ERROR:   [15] throw(error(existence_error(type,date),_37572))
ERROR:   [11] model:assert_campament('My campament', From, To, 'there', 'nothing') at /home/xxx/model.pl:9
ERROR:    [9] <user>
ERROR: 
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.

How can I persist date like types? In must_be/2, one of possible types is:

any any term
type Term is a valid type specification

Regards.

1 Like

From the page you linked:

TimeStamp

A TimeStamp is a floating point number expressing the time in seconds since the Epoch at 1970-01-01.

So just use float for the timestamp?

The DB module:

$ cat model.pl 
:- module(model, []).

:- use_module(library(persistency)).

:- persistent
   campament(name:atom,
             date_from:float,
             date_to:float,
             ubication:text,
             description:text).

The queries:

?- use_module(model).
true.

?- model:db_attach('data.db', []).
true.

?- parse_time('20180720', iso_8601, From),
   parse_time('20180729', iso_8601, To),
   model:assert_campament('My campament', From, To, 'there', 'nothing').
From = 1532044800.0,
To = 1532822400.0.

… and the contents of the database:

$ cat data.db 
created(1625778801.240848).
assert(campament('My campament',1532044800.0,1532822400.0,there,nothing)).

This solves your problem but doesn’t answer your question. I think it is possible to also declare compound types, but then I don’t think you can declare the types of the arguments of the compound. But maybe someone else can add something about this.

However, you should understand well enough why you need a compound term inside a table column. In most cases you should simply put each part of the compound in its own column. Depends on the use case of course.

2 Likes

Thank you. This is what I need.