Large programs are generally split into multiple files. If file A
accesses predicates from file B which accesses predicates
from file
A, we consider this a mutual or circular dependency. If
traditional load predicates (e.g., consult/1)
are used to include file B from A and A
from B, loading either file results in a loop. This is
because
consult/1
is mapped to load_files/2
using the option if(true)(.)
Such programs are typically
loaded using a load file that consults all required
(non-module) files. If modules are used, the dependencies are made
explicit using use_module/1
statements. The
use_module/1
predicate, however, maps to load_files/2
with the option
if(not_loaded)(.)
A use_module/1
on an already loaded file merely makes the public predicates of the used
module available.
Summarizing, mutual dependency of source files is fully supported with no precautions when using modules. Modules can use each other in an arbitrary dependency graph. When using consult/1, predicate dependencies between loaded files can still be arbitrary, but the consult relations between files must be a proper tree.