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"