Re: handling state the database way
Paul Singleton <[email protected]>
| Newsgroups | gmane.comp.ai.prolog.swi |
|---|---|
| Organization | Jambusters Ltd |
| Message-ID | <[email protected]> |
It might be good to have the same interface/API for state in the various places state can be, e.g. thread, http session, module,.. I wonder whether Logtalk facilitates this? Paul Singleton On 14/02/2014 18:28, Abdallah, Samer wrote: > 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