Hi Jan,
It’s likely that including the name of the module as an argument to experiment_file/2
points to some sloppiness in the code.
Fixing the experiment file module name is something I contemplated as a way to achieve what I want. I gave it the name world
to keep in line with the original post in this thread (which I hijacked - sorry!). In Louise, I’d fix that name to experiment_file
.
I haven’t actually implemented that scheme yet, the one where the experiment file name is fixed. But I do have a proof-of-concept example, that I share below. Note that I tried this outside Louise, in a fresh project, because the experiment file concept is entangled with everything in Louise and it will take some time to actually implement it and see if it really works. So I’m not 100% sure it’s exactly what I want. But, it seems to be close.
Below is the example of the scheme I plan to use in Louise. In the example, each module is a separate Prolog source file with the basesame name as its module name.
% Responsible for loading the experiment file listed in the configuration.
:-module(load_experiment_file, [load_experiment_file/1
]).
load_experiment_file(F):-
load_files(F, [module(experiment_file)
,redefine_module(true)
]).
% An experiment file module
:-module(experiment_file_1, [background_knowledge/2
,metarules/2
,positive_example/2
,negative_example/2
]).
% Experiment file interface predicates.
background_knowledge(t/2, []).
metarules(t/2, []).
positive_example(t/2, []).
negative_example(t/2, []).
% Another experiment file module
:-module(experiment_file_2, [background_knowledge/2
,metarules/2
,positive_example/2
,negative_example/2
]).
background_knowledge(p/2, []).
metarules(p/2, []).
positive_example(p/2, []).
negative_example(p/2, []).
Below is a session showing the intended use of the scheme above on the command line. In practice, load_experiment_file/1 would be called by the :-reload.
directive in the configuration file. This is not shown here.
% Load the named experiment file .
?- load_experiment_file(experiment_file_1).
true.
% Inspect the definitions of experiment file interface predicaes in the database.
?- listing([background_knowledge/2,metarules/2,positive_example/2,negative_example/2]).
experiment_file:background_knowledge(t/2, []).
experiment_file:metarules(t/2, []).
experiment_file:positive_example(t/2, []).
experiment_file:negative_example(t/2, []).
true.
% The database has the definitions in experiment_file_1, the loaded experiment file.
% Now, load a new experiment file:
?- load_experiment_file(experiment_file_2).
true.
% Inspect the definitions of interfce predicates in the database.
?- listing([background_knowledge/2,metarules/2,positive_example/2,negative_example/2]).
experiment_file:background_knowledge(p/2, []).
experiment_file:metarules(p/2, []).
experiment_file:positive_example(p/2, []).
experiment_file:negative_example(p/2, []).
true.
% The definitions in the new experiment file are in the database.
% Load the first experiment file again, to ensure there's no errors after multiple reloads/ unloads:
?- load_experiment_file(experiment_file_1).
true.
?- listing([background_knowledge/2,metarules/2,positive_example/2,negative_example/2]).
experiment_file:background_knowledge(t/2, []).
experiment_file:metarules(t/2, []).
experiment_file:positive_example(t/2, []).
experiment_file:negative_example(t/2, []).
true.
% And again
?- load_experiment_file(experiment_file_2).
true.
?- listing([background_knowledge/2,metarules/2,positive_example/2,negative_example/2]).
experiment_file:background_knowledge(p/2, []).
experiment_file:metarules(p/2, []).
experiment_file:positive_example(p/2, []).
experiment_file:negative_example(p/2, []).
true.
What I like in this scheme is that every query to the interface predicates can go through the prefix experiment_file:
rather than the actual name of the module- so it’s not necessary anymore to have the name of the module as an argument to the experiment_file/2
configuration option.
It’s also good to see that changing experiment files does not leave behind “garbage”, i.e. the definitions of interface predicates from a previously loaded experiment file. The following query assumes experiment_file_1
is currently loaded [edit: actually, experiment_file_2
is currently loaded!]:
?- listing(experiment_file_1:P).
true.
?- listing(experiment_file_2:P).
true.
?- listing(experiment_file:P).
negative_example(p/2, []).
positive_example(p/2, []).
metarules(p/2, []).
background_knowledge(p/2, []).
true.
Like I say, I don’t know 100% that this will work with the rest of the code in Louise and it will certainly take some wrangling to fit it in. That’s fine. But do you think the above can work and be stable across versions?
More to the point, is the example clear and simple, or would you like me to try and make a better one? I have a great talent for confusing everyone I talk to…
Edit: I’ve uploaded the three module files described above, for your convenience.
load_experiment_file.pl (235 Bytes)
experiment_file_1.pl (330 Bytes)
experiment_file_2.pl (330 Bytes)