handling state the database way
"Abdallah, Samer" <[email protected]>
| Newsgroups | gmane.comp.ai.prolog.swi |
|---|---|
| Message-ID | <[email protected]> |
Hello everyone, I'm not going to go on about DCGs this time, you'll be glad to hear. I'm trying to port/adapt various bits of code at the moment, and I am struck by how often dynamic predicates are used to keep state information, and how the same formulaic patterns are used, eg to change the state: :- dynamic some_pred/1. update(Event) :- retract(some_pred(OldState)), update_something(Event,OldState,NewState), assert(some_pred(NewState)). initialise : retractall(some_pred(_)), assert(some_pred( <Initial state> )). etc. Sometimes it is not obvious in the code that a predicate is being used this way, i.e., that there should only ever be one clause and it should be a fact, until one has gone through the code quite carefully. (My new predicate dependency graph drawing library has been quite useful for that, I will polish it up and make it into a pack soon…) The same issues apply to the recorded database. It obscures the meaning behind the code, it does not make the invariant (that there should only every be one clause) obvious, and it creates a risk that the invariant might be violated, e.g. if something goes wrong between retract and assert. The only facility that sort of addresses the issue is the flag/3 predicate, but that only works for atomic state values, and also, it's mode does not suit update operations, e.g. even to increment a counter, one cannot do this: flag(counter,C1,C2), succ(C1,C2). because C2 must be ground on entry to flag/3. As far as I can see, you would have to do this: flag(counter,C1,C1), succ(C1,C2), flag(counter,C1,C2). It would be nice if there was an apply_to_flag/2 predicate that would be called like this: apply_to_flag(counter,succ). or if you need the previous value: apply_to_flag(counter, get_succ(N)). get_succ(N,N,N1) :- succ(N,N1). and so on. I digress, but only slightly, because I think it would be good to have something like this that allowed an arbitrary term as state, with an interface something like: get_state(+Key, -Value) set_state(+Key, +Value) apply_to_state(+Key, CallableWithTwoArgs) state(+Key, -OldValue, +NewValue) Obviously, one could write a library to do this, but I think there might be benefit in performance, atomicity and control over backtracking behaviour that might come from it being integrated at a lower level, like flag/3. What do you think? Is it the case that the cost of doing unification on the state means that it is not worth the small gain of making it a built-in? cheers, Samer -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: <https://lists.iai.uni-bonn.de/pipermail/swi-prolog/attachments/20140214/f7f1673a/attachment.bin>