# Module\_property/2 - include property for super

**URL:** <https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804>\
**Category:** Request For Comments\
**Tags:** discussion\
**Created:** [August 19, 2020, 11:50am UTC](https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804 "2020-08-19T11:50:13Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [August 19, 2020, 11:50am UTC](https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804/1 "2020-08-19T11:50:13Z")

</div>

Internally (C code) SWI-Prolog modules have several properties. ([ref](https://github.com/SWI-Prolog/swipl-devel/blob/909fde0e9e66a011bb1e2e22c484e2a3edaf9426/src/pl-incl.h#L1777-L1805))

Many of the module properties are accessible via Prolog with module\_property/2.

One of the internal properties that is not accessible via Prolog is the list of supers.

Should `supers` should be added to module\_property/2?

I can’t think of a reason not to add the property supers, but then again I don’t understand SWI-Prolog at the C code.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [August 19, 2020, 1:30pm UTC](https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804/2 "2020-08-19T13:30:43Z")

</div>

Here is some code to create the relationships between modules by using predicate\_property/2 that I am expecting should be similar to what a `super` property for module would return.

After reply by Jan W. added section for import\_module/2.

```prolog
:- module(module_tools,[
        init/0,
        list_uses/1,
        list_imports/1,
        compare/0
    ]).

:- use_module(library(persistency)).

:- persistent
    uses(super:atom,module:atom),
    imports(module:atom,import:atom).

:- initialization(db_attach('module.journal', [])).

add_uses(Super,Module) :-
    (
        uses(Super,Module), !
    ;
        assert_uses(Super,Module)
    ).

init_uses :-
    forall(
            predicate_property(Super:_, imported_from(Module)),
            add_uses(Super,Module)
        ).

list_uses(uses(Super,Module)) :-
    uses(Super,Module).

add_imports(Module,Import) :-
    (
        imports(Module,Import), !
    ;
        assert_imports(Module,Import)
    ).

init_imports :-
    forall(
            (
                current_module(Module),
                import_module(Module,Import)
            ),
            add_imports(Module,Import)
        ).

list_imports(imports(Module,Import)) :-
    imports(Module,Import).

init :-
    init_uses,
    init_imports.

compare :-
    missing_imports,
    missing_uses.

missing_imports :-
    list_uses(uses(A,B)),
    (
        list_imports(imports(A,B))
    ->
        true
    ;
        format('Missing import: ~w, ~w~n',[A,B])
    ),
    fail.
missing_imports.

missing_uses :-
    list_imports(imports(A,B)),
    (
        list_uses(uses(A,B))
    ->
        true
    ;
        format('Missing uses: ~w, ~w~n',[A,B])
    ),
    fail.
missing_uses.

```

Example usage.

```prolog
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.5-8-ge14460a94)

?- working_directory(_,'C:/Users/Groot/Documents').
true.

?- ['module tools'].
true.

?- init.
true.

?- list_uses(Uses).
Uses = uses(prolog_source, system) ;
Uses = uses(prolog_source, prolog_operator) ;
Uses = uses(prolog_source, '$expand') ;
...

?- list_imports(Imports).
Imports = imports(prolog_source, system) ;
Imports = imports(swi_option, system) ;
Imports = imports(prolog_operator, system) ;
...

?- compare.
...
Missing import: prolog_metainference, lists
Missing import: prolog_metainference, apply
Missing uses: prolog, user
Missing uses: pce_expansion, user
...

```

If you want to look at the journal file created by library persistency remember that you have to execute `halt.` first. Also the code will hold a lock on the file while the code is running.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 19, 2020, 1:54pm UTC](https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804/3 "2020-08-19T13:54:20Z")

</div>

The internal notion of a _super module_ is the same as what is accessible through import\_module/2. What you are doing seems more related to library(prolog\_xref) or gxref/0.

I’m not really against exposing import\_module/2 also through module\_property/2, although this and its related default\_module/2 are non-deterministic and that isn’t ideal the module\_property/2 api.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [August 19, 2020, 2:15pm UTC](https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804/4 "2020-08-19T14:15:36Z")

</div>

> [@jan](#):
>
> The internal notion of a _super module_ is the same as what is accessible through [import\_module/2](https://www.swi-prolog.org/pldoc/doc_for?object=import_module/2).

Thanks. I will check this out and add a variation to my sample code if it proves useful.

* * *

> [@jan](#):
>
> What you are doing seems more related to library(prolog\_xref) or [gxref/0](https://www.swi-prolog.org/pldoc/doc_for?object=gxref/0).

Yes. I am starting to experiment with gxref/0 more, but it doesn’t have all of the functionality I would like. Granted when someone first learns to use a tool and the way they eventually use it can be quite different, that might be the case.

For example if I drag `library(system)` or `library(lists)` onto the canvas area then right click the following options appear

![image](https://global.discourse-cdn.com/free1/uploads/swiprolog/original/2X/3/38cfd741cbccf7e1bf103223b2c60027125cd41d.png)

but for me clicking on `Show exports` or `Show imports` does nothing.

I am on Windows 10.

While I can run X-Windows with WSL 2 on Windows 10, currently enabling X-Windows with WSL 2 grinds the system to a near halt and becomes impractical to use.

* * *

The specific need is to do an inheritance of predicates similar to Object-Oriented. The predicates are for the BNF for rfc5234, rfc3986, and rfc7230 which each extend from the previous and thus inheritance. However unlike inheritance, some of the predicates will not replace the ones in the preceding rfc but work along side them, think multi-clause predicate.

I experimented with [oo.pl](https://swi-prolog.discourse.group/t/threaded-queries-rulebase-independence/1236/24) from here but then realized that it is not the call stack (prolog frame) that I should be traversing, but the hierarchy of the modules.

Anyway the only way to know if what I seek is doable is to just try it.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 19, 2020, 2:42pm UTC](https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804/5 "2020-08-19T14:42:02Z")

</div>

> [@EricGT](#):
>
> but for me clicking on `Show exports` or `Show imports` does nothing.

Indeed, seems broken. Double clicking shows the proper dependencies, so this seems more a GUI issue.

> [@EricGT](#):
>
> However unlike inheritance, some of the predicates will not replace the ones in the preceding rfc but work along side them, think multi-clause predicate.

Not sure I get this. Surely though, a module import never extends a predicate. The only way to do that is to add a clause calling the super. So, assume we have s:p/1 and t:p/1 and t:p/1 should be extended with s:p/1 we get in `t`:

```prolog
p(1).
p(2).
...
p(X) :- s:p(X).

```

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [August 19, 2020, 3:14pm UTC](https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804/6 "2020-08-19T15:14:56Z")

</div>

> [@jan](#):
>
> Not sure I get this.

That makes two of us.

It is hard to explain where one is going when one is not sure about where one needs to go.

> [@jan](#):
>
> Surely though, a module import never extends a predicate.

Yes.

It seems that to solve my specific problem I have a few choices.

1. Duplicate code. This works and was done by creating a single module with all of the predicates needed for each RFC. This essentially was done by taking the preceding RFC and duplicating the code then adding the new predicates. Thus each RFC required a new and unique module.

2. Use multifile/1. In one of the ways I did get the code working was to use multifile/1 for some of the predicates, but while I understand what I did and why, trying to write that up for a Wiki article or something requires an in-depth explanation of parsing, inheritance, Prolog, etc, that I would run away in horror if I read it and never use it.

3. Abandon the module system. I have considered making predicates that replace use\_module/1,2 with something like inherit\_module/1,2 but that is not even a correct conveyance of the what needs to be done. In all my years of using inheritance with OO, I don’t recall the notion of something like multi-clause predicates being used with inheritance. Especially when on of the clauses would be in one module and the other would be in another module.

4. Manage the exports and imports by hand and use Module:Predicate where necessary. This also came to rely on needing multifile/1 to work, thus turned out not to be a separate solution.

5. A variation on oo.pl. This is the one I am working on now that needs `super`.

6. Using expand\_term/2 or similar. A future option as a plan B, or to be used with another option if it is to complex to explain in a Wiki article.

* * *

> [@jan](#):
>
> The only way to do that is to add a clause calling the super. So, assume we have s:p/1 and t:p/1 and t:p/1 should be extended with s:p/1 we get in `t` :
> 
> ```prolog
> p(1).
> p(2).
> ...
> p(X) :- s:p(X).
> 
> ```

This is closest to what seems to be the correct path and thus the need for knowing the super. I still don’t see all of the potential problems so will just write the code and hopefully it will work as expected.

Thanks. 🙂

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 19, 2020, 3:39pm UTC](https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804/7 "2020-08-19T15:39:52Z")

</div>

> [@jan](#):
>
> > [@EricGT](#):
> >
> > but for me clicking on `Show exports` or `Show imports` does nothing.
> 
> Indeed, seems broken. Double clicking shows the proper dependencies, so this seems more a GUI issue.

In fact, the code was designed not to include imports and exports from libraries in the dependency view as it quickly gets a mess. Should work fine on your own modules.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 21, 2020, 7:21am UTC](https://swi-prolog.discourse.group/t/module-property-2-include-property-for-super/2804/9 "2020-08-21T07:21:33Z")

</div>

Besides import/export, SWI-Prolog modules can inherit in a different way. That is realised by import\_module/2 and predicates from the same manual section. It implies that if a predicate is not defined the system examines the import modules one-by-one and when found, auto-imports the definition. A module can have multiple import modules (rarely used). You can form a lattice of import modules, etc.

This is not proper OO. There is no notion of _self_ and also no real notion of _super_, so a module cannot wrap its general notion of super, it can only wrap the implementation from a known concrete module. You can achieve some stuff using the _module transparent_ notion, but that is more hacking than anythng else.
