Modules (was Re: predutils package available (Re: PAC library for develop version available))

Jan Wielemaker <[email protected]> Thu, 2 Oct 2014 18:01:42 +0200
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <[email protected]>
On 10/02/2014 05:35 PM, Kuniaki Mukai wrote:

> Although your answer has made me clear, let me put my intended
> question in more concrete way. Suppose two module files "mod_a.pl" and
> a `child` module "mod_b.pl" defined as follow:

Note that there is not really a notion of `child' modules.  Modules
can use each other (even mutually, by importing each other).

> %%%% file mod_a.pl %%%
> :- module(mod_a, [hello/0]).
> :- use_module(mod_b).
> hello :- writeln('hello from ma.').
> 
> %%%% file mod_b.pl %%%
> :- module(mod_b, [world/0]).
> world :- writeln('world from mb').
> 
> % ls
> mod_b.pl	mod_a.pl

> ?- use_module(mod_a).
> true.
> 
> ?- hello.
> hello from ma.
> true.
> 
> ?- world.
> Correct to: "mod_b:world"? 
> Please answer 'y' or 'n'? 
> ERROR: '$execute_goal2'/2: Undefined procedure: world/0
> ERROR:   However, there are definitions for:
> ERROR:         mod_a:world/0
> ERROR:         mod_b:world/0
>    Exception: (6) world ? abort
> % Execution Aborted
>  
> I believed wrongly that imported predicates from "child modules" may get
> global under some context.  In fact, I expected no error message for that
> query.

That is indeed not what happens.  If you want that though, you can do two
things: export world/0 also from mod_a.pl, as in

:- module(mod_a, [hello/0, world/0]).
:- use_module(mod_b).
hello :- writeln('hello from ma.').

Or re-export:

:- module(mod_a, [hello/0).
:- reexport(mod_b).
hello :- writeln('hello from ma.').

rexport/1 is a simple use_module/1, followed by adding all
public predicates of the imported module to the export list
of the importing module.

In most situations, I'd go for the first solution with explicit
export of the imported predicates, as this makes it much easier
for the reader to see what you get from a module.  The reexport
was mainly added to create libraries derived from similar libraries
for portability reasons.   So, if I want to write a YAP compatible
library(lists), I can of course start from scratch.  But, 95% is
the same anyway, so I can write a library like this:

:- module(yap_lists, [ extra-stuff, ...]).
:- reexport(library(lists), except([ incompatible stuff ]).

<definitions for the extra and incompatible stuff>

Now, I've saved myself a lot of typing and at the same time
make it obvious what is different between the two modules.

> My question was really stupid, but I appreciate a lot for
> your taking time. I hope I am the only such a prologer.

Quite unlikely :-)

	Cheers --- Jan