moduleswi-prologmeta-predicate

What modules does an unqualified assert add a term to?


?- assertz(:- module(foo1, [f/1])).
true.

?- foo1:assertz(f(1)).
true.

?- foo1:f(1).
true.

?- foo2:f(1).
Correct to: "foo1:f(1)"? no
ERROR: Undefined procedure: foo2:f/1
ERROR: In:
ERROR:    [8] foo2:f(1)
ERROR:    [7] <user>

Makes sense to me. But then (from scratch)....

?- assertz(:- module(foo1, [f/1])).
true.

?- assertz(f(1)).
true.

?- foo1:f(1).
true.

?- foo2:f(1).
true.    # Wait, what? foo2 doesn't appear in my program. Should fail?

?- frobnoz:f(1).
true.    # Also odd!

But then...

?- foo2:assertz(f(1)).
true.

?- foo2:f(1).
true.

?- frobnoz:f(1).
ERROR: Undefined procedure: frobnoz:f/1

How does f get added to foo2 when I don't mention foo2. Why does frobnoz:f succeed in the second example, but fail in the third?

What are modules? I thought they were namespaces, but am now confused.


Solution

  • 1st question:

    How does f get added to foo2 when I don't mention foo2.

    From SWI-Prolog Manual - Module autoload section:

    SWI-Prolog by default support autoloading from its standard library. Autoloading implies that when a predicate is found missing during execution the library is searched and the predicate is imported lazily using use_module/2.

    You can go deeper but, basically, when the module is not explicitly defined, prolog search for it and silently loads it. It's the default behavior. You can change it with autoload flag.

    2nd question:

    Why does frobnoz:f succeed in the second example, but fail in the third?

    Probably this frobnoz:f can be found as a dependency from foo1 module, which you are not referencing in the third example.

    3rd question:

    What are modules? I thought they were namespaces, but am now confused.

    As SWI-Prolog Reference Manual reads:

    A Prolog module is a collection of predicates which defines a public interface by means of a set of provided predicates and operators. Prolog modules are defined by an ISO standard. Unfortunately, the standard is considered a failure and, as far as we are aware, not implemented by any concrete Prolog implementation. The SWI-Prolog module system syntax is derived from the Quintus Prolog module system. The Quintus module system has been the starting point for the module systems of a number of mainstream Prolog systems, such as SICStus, Ciao and YAP. The underlying primitives of the SWI-Prolog module system differ from the mentioned systems. These primitives allow for multiple modules in a file, hierarchical modules, emulation of other modules interfaces, etc. (source)

    In classic Prolog systems, all predicates are organised in a single namespace and any predicate can call any predicate. [...] A Prolog module encapsulates a set of predicates and defines an interface. Modules can import other modules, which makes the dependencies explicit. Given explicit dependencies and a well-defined interface, it becomes much easier to change the internal organisation of a module without breaking the overall application. (source)

    Typically, the name of a module is the same as the name of the file by which it is defined without the filename extension, but this naming is not enforced. Modules are organised in a single and flat namespace and therefore module names must be chosen with some care to avoid conflicts. As we will see, typical applications of the module system rarely use the name of a module explicitly in the source text. (source)