Side-Effects in Compile-Time Code

One other way to add clauses to qpc's internal database is to assert them in an embedded command. For example, the sequence:

     :- asserta(f(x)).
     :- f(X), write(X), nl.
     

in a file given to qpc will work just as it would if the file were compiled into the Development System.

There are some problems with asserting clauses like this. One problem is that the asserted clauses will not be available at run-time. If the file had been loaded into the Development System, they would be available when the program was run.

Another problem arises if the compilation of one file depends on facts that are expected to be asserted into the database during the compilation of some other file. An approach of this sort may be useful in the Development System, but it is contradictory to the notion of independent compilation (see the first figure), which is one of the important features of qpc. This problem is not specific to asserting clauses; it arises with any compile-time side-effects that are intended to affect future compilation.

It is possible to avoid using separate compilation, by always recompiling your entire program every time any part of it is modified. It is still not generally safe to use compile-time side-effects in one file that affect the compilation of other files. This is because the order in which files are compiled is different in qpc. When qpc finds a command to compile a file, it looks in that file immediately to find out whether it is a module-file and if so what are its exports. But it does not actually compile the file immediately: it puts it on a queue to be compiled when the current file has been finished with. This is in contrast to compilation in the Development System, where embedded compile/1 commands are processed immediately as they are encountered.

Therefore, it is strongly recommended that side-effects in compile-time code be avoided, or at least restricted so that only the compilation of the current file is affected.