I'm just getting involved in using Prolog to handle more than just the simplest forms of data (facts) and am looking for some guidance from the seasoned Prologers...
If I want to dynamically manage data or facts, I have a couple of major choices, such as do I:
If I manage facts as assertions in Prolog, I also have the question of the best way to represent those facts. Let's suppose I have a person
who has a first name, last name, and an age. I can assert it as:
person(first_name(_), last_name(_), age(_)).
Or have an implicit assumption of what the attributes of person are:
person(_, _, _). % first name, last name, age
If I want to associate a person with something else, I really need a key for a person. So I might be inclined to assert a person as:
person(id(_), ...). % Maintain id as a uniq person key; or done implicitly as above
Of course, now I'm making my Prolog assertions look like relational database table entries. And it makes me wonder if I'm taking the wrong approach and overly complicating the representation of facts.
So really, my question is: Are there some best practices to consider when managing medium to complex data in Prolog? The naming convention is the small side of it. I've read bits like the assert/retract in Prolog are inefficient. So I'm also wondering about how to approach the data organization itself, like when to resort to an external SQL database versus Prolog-only representation.
ADDENDUM
I would assume that use of a key for records, as is done in a relational database, would be desirable for the very reasons a relational database uses them. Which means that the key must be maintained. It seems cumbersome to do this manually (explicitly) in Prolog for each case, so how is this done generally? Or is my assumption in correct?
Consider using a more descriptive name for your predicate, for example:
id_fname_lname_age(_, _, _, _)
.
This explicitly denotes what the arguments are without needing any additional structures.
In my opinion, a good rule of thumb for naming predicates is to describe the arguments in the order they appear in, using declarative names, separated by underscores.
EDIT: As to your additional questions: assertz/1
is slow (and has many other disadvantages) in comparison to a nicely declarative programming style that simply passes arguments between predicates that do not intrinsically require any modifications of the clause database. When you really need to assert additional facts because you are using Prolog like a relational database system, then assertz/1
is one way to do it (other options are mentioned in other answers here), and will likely be comparable in efficiency to any other relational database system for many usage scenarios. As already mentioned, several modern Prolog systems perform just-in-time indexing on all arguments, and you therefore need not explicitly declare any "keys".