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>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.