Subject: Re: [SWIPL] using modules

From: "Richard A. O'Keefe" <[email-masked]>
Date: Mon, 5 Feb 2001 13:25:04 +1300 (NZDT)

<[email-masked]> asked:
    1) In prolog I may create [a] module.  But how [can I] destroy [a] module?

Strictly speaking, you cannot create a module in Prolog.
Every possible module exists:  you can assert facts into modules that
have never been mentioned before.

Let me show you what you can do in Quintus Prolog:

    f% cat m1.pl
    :- module(m1, [a/1]).
    a(b).
    f% cat m2.pl
    :- module(m2, []).
    f% qp
    [banner deleted]
    | ?- [m1].
    % compiling file /home/users/okeefe_r/sgml.d/ou.d/m1.pl
    % m1.pl compiled, 0.020 sec 828 bytes
    % module m1 imported into user

    yes
    | ?- [m2].
    % compiling file /home/users/okeefe_r/sgml.d/ou.d/m2.pl
    Module m1 is being redefined in a different file.
	Previous file: /home/users/okeefe_r/sgml.d/ou.d/m1.pl
	New file:      /home/users/okeefe_r/sgml.d/ou.d/m2.pl
    Do you really want to redefine it? (y/n/a) y
    % m2.pl compiled, 0.030 sec 36 bytes
    % module m1 imported into user

Loading an empty definition of m1 with no exports from m2.pl has wiped out
everything that was known from m1.pl; a link between module m1 and file m2.pl
remains, but that is no barrier to putting other contents in that module.

SWI Prolog, unfortunately, not only notices that you are trying to redefine
a module, but refuses to do it, without considering that you might have meant
to do it, or asking you to confirm its action.

It would be better if SWI Prolog asked, like Quintus Prolog.

    2) I may consult(File). But how [can I] deconsult(File)?

The obvious code is

deconsult(File) :-
    absolute_file_name(File, Abs),
    (/* Look for a module */
        current_module(Module, Abs),
	source_file(Module:Head, Abs),
	functor(Head, Symbol, Arity),
	abolish(Module:Symbol/Arity),
	fail
    ;/* look outside modules */
        source_file(Head, Abs),
        functor(Head, Symbol, Arity),
        abolish(Symbol/Arity),
        fail
    ;/* no more places to look */
	true
    ).

However, there is a curious bug in SWI Prolog that means this won't work.
I revised m1.pl to read
    :- module(m1, [a/1]).
    a(b).
    b(c).
and then tried
    ?- deconsult('m1.pl').
to be told
ERROR: Arguments are not sufficiently instantiated
^  Exception: (7) source_file(m1:_G277, 'DIR/m1.pl').

But
    source_file(P, 'DIR/m1.pl')
succeeded with P = m1:b(_), so the arguments *were* sufficiently
instantiated to compute a result, and what's more.

Turn it around, therefore, getting.

deconsult(File) :-
    absolute_file_name(File, Abs),
    source_file(Pred, Abs),
    (   Pred = Module:Head ->
	functor(Head, Symbol, Arity),
	abolish(Module:Symbol/Arity)
    ;/* there isn't a module prefix */
	functor(Pred, Symbol, Arity),
	abolish(Symbol/Arity)
    ),
    fail.
deconsult(_).