Re: handling state the database way
Paulo Moura <[email protected]>
| Newsgroups | gmane.comp.ai.prolog.swi |
|---|---|
| Message-ID | <[email protected]> |
On 18/02/2014, at 10:05, Jan Wielemaker <[email protected]> wrote: > On 02/18/2014 10:36 AM, Paulo Moura wrote: >> The design idea behind the "single_fact" module centralizes (for an >> application) the handling of mutable data. This can be both an >> advantage (a single place to hold the mutable data) and a >> disadvantage (multiple modules using this module must be careful to >> use different keys). This makes "single_fact" more like a *prototype* >> solution than an ideal *library* solution. As a library solution it >> comes with a bias towards a single central, global store. >> >> Logtalk provides a bit more flexible library solution by using a >> category instead. A Logtalk category is a fine-grined unit of code >> reuse that can be (virtually) imported by any object. Using the >> "single_fact" module suggested predicates, we can define: > > Logtalk's abstracting has a cleaner design than classical Prolog > modules, Thanks :-) > but that doesn't mean we can't realise module local > storage with Prolog modules: Sure it's possible. That's one of the reasons I referred to the original "single_fact" module as a prototype solution. > :- meta_predicate > initialize(:, +), > ... > > initialize(Module:Key, Value) :- > asserta(Module:store(Key, Value)). > > ... > > And the central store is just > > initialize(central:size, 42). So we moved from a first "single_fact" module prototype to a second, arguably more flexible one: :- module(single_fact, [ initialise/2, access/2, update/2, finalise/1 ]). :- meta_predicate initialise(:, +), access(:, +), update(:, 2), finalise(:). :- dynamic store/2. initialise(Module:Key, Datum) :- retractall(Module:store(Key,_)), assert(Module:store(Key, Datum)). access(Module:Key, Datum) :- Module:store(Key, Datum). update(Module:Key, Updater) :- retract(Module:store(Key, Old)), !, /* green cut */ ( call(Updater, Old, New) -> F = true ; New = Old, F = fail ), assert(Module:store(Key, New)), F == true. finalise(Module:Key) :- retractall(Module:store(Key,_)). The caveats with this solution: (1) the keys *may* need to be explicitly qualified, depending on the usage scenario; (2) looking into code of the modules using the "single_fact" module it's not apparent that each using module now also have a store/2 dynamic predicate. (1) may be a nuisance when handing keys or simply a no-problem. (2) it's interesting by its own from a tools perspective. In the case of the Logtalk solution, the declaration of the private and dynamic store/2 predicate is inherited by the objects importing the category. In the case of the module solution, *after* the store being initialized, the query current_predicate(central:sore/2) succeeds. Cheers, Paulo ----------------------------------------------------------------- Paulo Moura Logtalk developer Email: <mailto:[email protected]> Web: <http://logtalk.org/> -----------------------------------------------------------------