Importing a foreign predicate that was registered in a module

When defining foreign predicates, it’s possible to define them in a particular module using PL_register_foreign_in_module("some_module_name", "some_predicate_name", ...). After loading the foreign library, the predicate can be called in prolog using some_module_name:some_predicate_name(...).

For normal prolog code, we can use use_module(some_module_name) to load a module file and import its predicates into the current module. For the foreign library case however, there seems to be no way to import the predicates, except for the case where they were registered without module, in which case they’ll go into whatever module loaded them.

The result of this is that whenever a predicate is explicitly registered with a module, calling code is forced to always call this predicate with a module specifier. This seems odd. Is there no way to directly import a foreign module?

The one workaround I found to this is that we can define a prolog module file that defines a module with the same name and exports the foreign predicate using :- module(some_module_name, [some_predicate_name/1]), which can then be used with use_module as usual. Is this how I should go about doing this?

The first question is of course why you would like to define a foreign predicate in a specific module not being the module that loads the foreign code?

I don’t recall for what scenario PL_register_foreign_in_module() was intended. It is otherwise the same as ?- assertz(mymodule:hello(world))., where mymodule is not a module that belongs to a file. You can use export/1 to export it from the dynamic module and import/1 to import it into a new context. use_module/1,2 only works with files (as you noticed).

1 Like

With TerminusDB we’ve recently added a foreign module to the build. This is intended for any sort of predicate we wish to accelerate by writing it in rust instead of prolog, but which doesn’t really make sense as a library, or for which the overhead of creating a new library may be (mentally) inhibitive in actually making the effort. Basically, we want to make it as easy as possible for ourselves to write some stuff in rust instead of prolog. So over time this is going to become a big shared module containing a wide assortment of predicates.

We could have all those predicates share the same module name, in which case declaring no explicit module name and importing it in a special native-code module would totally work for us. However, I feel like it kinda makes sense to use module names to split out different sorts of functionality, just like we’d ordinarily do with prolog predicates. So declaring explicit module names kinda makes sense to me.

I think the easiest way to work with this then is either to just accept we have to use module prefixes, or to create a module dummy file that does the explicit export.

Thanks for your explanation :).