Hi! Is there a way to run chr in sandbox, or just using a new (empty) constraint store? I am using CHR in a library and the problem is that a second call to the library predicate, reuses same CHR module and constraints get reused.
CHR constraints are module specific. So rules you define in your module won’t directly interact with rules defined by a library. But if you want to use the same module twice, that won’t help. (Is there a prolog facility to load a module twice, but into two separate namespaces?)
The other way to separate invocations of a constraint is to add a groupid parameter.
x(Groupid, …)
y(Groupid, …)
If that’s there then x(3, …), y(3, …) won’t interfere with x(2, …), y(2, …).
But if your library of CHR rules doesn’t provide either of those, I’m afraid you’re stuck.
I notice with the toy examples the writers provide, this grouping isn’t used. They will define for example incremental sort predicate whose only parameters are the things to be sorted. Which is a limitation if you have 2 sets of things to be sorted.
There’s one other option: You can run a separate thread, as each thread has its own store.
Thanks for the thread hint, this might do it as a workaround. As a temporary solution, I added a new constraint cleanup/0
and bunch of simpagation rules with all other constraints to removes them after I computed the answer and bound it to variable.
To clarify my initial question, I am writing a library myself that uses CHR under the hood, but the problem is that if user of the library calls the predicate multiple times, then the constraints are not cleared between runs. I was hoping I can just use something like chr_destroy_store(my_library_module)
after each run.
I think that is how it is intended to be used. It shouldn’t be too hard to add a chr_cleanup/0 though. The constraints are stored in a number of global variables, so you have to find them and delete them using nb_delete/1. AFAIK they are recreated lazily when needed. If not, instead of deleting set them back to their initial value. Maybe create a PR?
Threads (or engines) are indeed another work-around.
If it’s your own library, simply add a parameter for the call id and you can have multiple parallel queries.