[comp.lang.prolog] recorda/3 etc.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (07/02/90)

In article <NICKSON.90Jul2160643@vuwcomp.comp.vuw.ac.nz>,
Ray.Nickson@comp.vuw.ac.nz (Ray Nickson) writes:
> I'm interested to know whether the use of the `Internal Database'
> predicates (recorda/3, recorded/3, erase/1 etc.) of Edinburgh Prologs
> is considered good programming.

erase/1 is quite general; it can be used to erase ordinary clauses
as well as data base records.  instance/2 can also refer to ordinary
clauses.

I used to use the recorded data base a fair bit, so I would say that at
one time it was good programming.  But it can't be considered PORTABLE
programming.  There are one or two Prolog systems around which pretend
to have these operations but get them wrong, and there are several which
lack them entirely.

> Now I read in the (unreleased) SICStus 0.7 #BETA manual:
>   The predicates described in this section were introduced in early
>   implementations of Prolog to provide efficient means of performing
>   operations on large quantities of data.  The introduction of indexed
>   dynamic predicates has rendered these predicates obsolete, and the sole
>   purpose of providing them is to support existing code.  There is no
>   reason whatsoever to use them in new code.
> Taken with the Quintus assertion that they are for efficiency only,
> this sounds like a pretty strong deprecation of their use.

In DEC-10 Prolog, the recorded data base was essentially an array of
512 two-way linked lists of terms.  When you stored something in the
recorded data base, the bottom 9 bits of an integer (or of a functor's
magic code) were taken as a "hash" code and the term was dropped into
the appropriate place in the bucket.  A data base reference was really
just a disguised memory address (and still is).

Data base references give you two things:
(1) UNIQUE NAMES for clauses and records.  This is the most important
    thing about them.
(2) Constant-time access to the clause named by a reference.
These advantages apply whether you are using the recorded data base or not.

Use of the recorded data base gave you two things:
(3) a level of indexing beyond what dynamic predicates gave you
(4) a GUARANTEE that no program code would be affected.

Now, it is quite possible to emulate the recorded database:

	?- dynamic
		'internal record'/2.

	recorda(Key, Term, Ref) :-
		nonvar(Key),
		same_functor(Key, Clavis),
		asserta('internal record'(Clavis,Term), Ref).

	recordz(Key, Term, Ref) :-
		nonvar(Key),
		same_functor(Key, Clavis),
		assertz('internal record'(Clavis,Term), Ref).

	recorded(Key, Term, Ref) :-
		clause('internal record'(Key,Term), Ref).

	instance(Ref, Term) :-
		/* This is simplified, but close enough */
		clause('internal record'(_,Term), true, Ref).

(Taken literally, this would mean that you could use integers and floats
as keys.  It SHOULD be taken literally, because you CAN.)

    Given a Prolog system which indexes dynamic predicates, this is going
to give you as much indexing as DEC-10 Prolog ever gave the internal data
base.  (Other Prolog systems may do _more_ indexing for the internal data
base, so there may still be some point in using it.  Check your manual.)

    What about the guarantee that no program clauses will be smashed?  Ah,
all you ever needed for THAT was the discipline of using SOME interface
in your code instead of using bare asserts and retracts.  But that would
have been good programming style anyway, whether the internal data base
had existed or not.

    The recorded data base is a global resource, just like property lists.
If an implementor has encroached on it and has some keys of his own that
you mustn't touch (or, for a Prolog with property lists, some properties
that you mustn't touch) that is a glaring DANGER signal, a clear sign that
you shouldn't use it at all.

    Generally speaking, what you should do is define your own interface
for "global data", and put the implementation of it in a separate file.
Make sure that your program uses that interface instead of bare asserts
and retracts.  Your implementation can use the recorded data base if you
have it.  If you are using a Prolog with modules and indexed dynamic, it
can use that instead.

    Once Quintus Prolog acquired modules and indexed dynamic (release 2.0,
how long ago it seems now) I gradually stopped using the recorded data
base.  Even without modules I'd probably not bother going back.

-- 
Science is all about asking the right questions.  | ok@goanna.cs.rmit.oz.au
I'm afraid you just asked one of the wrong ones.  | (quote from Playfair)

Ray.Nickson@comp.vuw.ac.nz (Ray Nickson) (07/03/90)

I'm interested to know whether the use of the `Internal Database'
predicates (recorda/3, recorded/3, erase/1 etc.) of Edinburgh Prologs
is considered good programming.   The C Prolog User's manual says
`they are intended for more sophisticated database applications and
are not really necessary for novice users' (but doesn't say how an
application qualifies as sophisticated!), the Quintus manual says they
are for efficiency only.  The current SICStus prolog manual says
`[they] are primarily concerned with providing efficient means of
performing operations on large quantities of data.  Most users will
not need to know about these predicates.', and goes on to say they
allow separation of program and data: `Note the diference between this
facility and that provided by `assert/1' and related predicates: the
latter actually alter the running program.'

I just discovered these predicates, and thought they were a tidy way
of achieving just that separation.  I intended to use them for keeping
around `global' data (whatever the logical purity considerations, I
always seem to need to do this!) instead of using assert/1 as I
currently do; this use feels much less like self-modifying code than
does code using assert/1 and clause/2, and I don't have the niggling
worry about running into the grey area of modifying a
currently executing predicate.
 
Now I read in the (unreleased) SICStus 0.7 #BETA manual:
  The predicates described in this section were introduced in early
  implementations of Prolog to provide efficient means of performing
  operations on large quantities of data.  The introduction of indexed
  dynamic predicates have rendered these predicates obsolete, and the sole
  purpose of providing them is to support existing code.  There is no
  reason whatsoever to use them in new code.
Taken with the Quintus assertion that they are for efficiency only,
this sounds like a pretty strong deprecation of their use.

Opinions?

-rgn
--
Ray Nickson <Ray.Nickson@comp.vuw.ac.nz>                    + 64 4 721000x8145
                 "everything is alright when you're down"