I want the code to: I want to be able to create a context for temporary use and then get rid of it. I see that one can set a module property of temporary, but I don’t see explanation of the meaning of this. Is it only for use with in_temporary_module, or can programmers use it directly? If one creates a module and marks it as temporary, how does one signal that one is done with it?
I think this is a great question, I often wish I had this. The point is that while I can create a module dynamically, it’s not clear to me if it can be garbage collected when I don’t need it anymore. In practice, I retract every fact contained in that module, and then pretend it never existed, figuring the overhead is probably minimal. But I wish I knew of a more elegant solution.
In general, I find that using modules as temporary containers for facts instead of data structures (like a list of facts) is a very natural idea, but doesn’t have enough attention from an usability perspective in prolog. And I don’t really understand why.
Temporary modules are rather fragile. in_temporary_module/3 captures the scenario for which it was intended. If that doesn’t suit you, please explain your scenario.
That is exactly what in_temporary_module/3 does: the Setup argument creates the context in the module and Goal is executed in this context.
I think you have already discussed this question a little elsewhere: this is by way of being a follow-up.
I am using the Popper ILP system, which uses SWI Prolog to evaluate learned rule sets (invoking SWI through the Janus library). A challenge is that Janus does not (as far as I can tell) permit resetting the Prolog to work on a new rule set; attempting to do so causes Prolog errors.
More specifically, the test component of Popper queries against the learned ruleset (and some fixed background knowledge) to see if the ruleset correctly labels all of the positive and negative examples. Currently this is done with multiple queries (the python code has approximately 25 invocations of query_once), so it’s not obvious how to it to make use of in_temporary_module, which handles only a single goal.
The simplest and most robust way is probably to create a single query The second option is to look at the implementation of in_temporary_module/3 and use the building blocks directly. That is not officially supported as it uses undocumented predicates whose name start with $. It is not very likely something will change to these shortly though. You have to obey two rules
Make sure no other module imports anything from the temporary module.
Make sure no query is running when you destroy the temporary module.
You were kind enough to explain to me how to use a temporary module so that I could garbage-collect a bunch of code in an ILP system (Popper).
I have tested this out, and I find that it works correctly, but the version using a temporary module runs much more slowly, especially for a large problem. I conjecture that this is because the code in the temporary module is not being compiled. Is that correct?
If so, is there any way to abolish all code in the user module so that it can be reloaded?
I believe it’s possible to look at the ILP problem and determine whether it will be expensive to solve, and modify one’s approach to handling it.
Should not be the case. There is nothing special about temporary modules in how code is handled. You should only avoid any other code relying on the code in temporary modules as in the end the code is deleted.
I’d first try using the profiler to see whether can can find what exactly is slower.
Thank you for the quick and helpful reply! I will try the profiler, and will also be examining what specific problem features are correlated with the slow-down.