I have created an association list and I want to use it from all the predicates I have like if it is a global variable. How can I update its content and succeed to pass it through the predicates at its latest version ?
If you use edcg, you can define an accumulator is passed “invisibly” between predicates.
(I’m travelling, so don’t have time to give you more details.)
Same as in your other post about keys, answered in stackoverflow.
There are several sensible solutions but selecting one ultimately depends on the details of your use case.
As Paul Brown suggested in his StackOverflow answer, a simple solution is just to use a predicate holding the “state” for that “global variable”. For example, assume that you have a some threshold that you want to share. you can define a threshold/1
predicate and then call it from all predicates that need to access its current value. You can declare the threshold/1
predicate as a dynamic predicate so that you can use the assert and retract predicates to update it (in a multi-threaded application, you may need to protect access to the predicate when updating it). This is a good solution if the “state” you want to share is a relatively simple term (not clear if that’s the case here; how many key-value pairs in your association list?) and if the predicates only require accessing its “value”, never modifying it (meaning that there’s a single point in your code where the “state” is updated).
Peter Ludemann mentioned EDCGs, the big brother of DCGs. Grammar rules are a threading state abstraction where the arguments representing the state are abstracted. Your question suggest that the threading part is not required, however. It is of course possible to use grammar rules simply to pass state but then the abstraction becomes overkill.
A key factor is how the association list (aka dictionary) you mention is created and updated. Using a predicate to store it requires the predicate to be dynamic but does the process that creates and updates the dictionary requires saving it to the database? If that’s not the case, passing the dictionary as an additional argument would result in a more declarative solution. Passing the dictionary as an additional argument can be done explicitly (by modifying the predicates that require access) or implicitly (e.g. using Logtalk parametric objects with the dictionary passed as a parameter). Ask yourself: can your application backtrack over dictionary updates? If that’s the case, you want to hold and pass the dictionary using a logical variable, not the database (as assert and retract are non-backtracable operations).
Finally, is the specific implementation of a dictionary that you mention, library(assoc)
, a definitive choice? There are other alternatives (e.g. library(rbtrees)
) that may be worth considering. Unfortunately, these alternative have different interfaces in Prolog making experimenting painful (for multiple implementations of a dictionary sharing the same interface see in alternative Logtalk’s dictionaries
library).