Prolog modules are objects. This statement may surprise you. From past experience, it will also annoy some Prolog practitioners. It is not the case that the creators of Prolog module systems intended to create an object-oriented extension to Prolog. But what modules are is a function of their characteristics, not a function of their design intentions 1.
How is the OOP notion of a prototype materialized by a Prolog module? Let’s consider the defining characteristics of a prototype one-by-one:
This is the most basic characteristic of an object in any OOP language. It’s also a basic characteristic of Prolog module systems that each module have a unique identity (an atom).
Prototypes can be created ex-nihilo (i.e. from scratch). Likewise, a Prolog module can be defined in a source file or dynamically created at runtime. For example, the following query creates a module named
foo in most module systems (a notable exception being the ECLiPSe module system):
Prototypes can also be created by expressing how they differ from other prototypes, know as their parent prototypes. With modules, we can use the
reexport/1-2 directives to achieve similar functionality 2.
Although explicitly-qualified module predicate calls don’t perform the lookups associated with messages, they can still be interpreted as messages in a prototype system. With a standalone prototype, message lookup only considers the prototype itself. Likewise, if a module doesn’t reexport other modules (or reexport predicates from other modules), implicit or explicitly, them an explicitly-qualified predicate call only checks the module itself. When a prototype extends (or is derived from) other prototypes, message lookup will follow the derivation chain(s). Likewise, if a module reexports other modules (or reexports predicates from other modules), an explicitly-qualified predicate call will work for any predicate in the reexport chain(s).
Note: the main motivation for this blog post is the well intended advice of some people in the community that Logtalk is handy when you need some OOP in your Prolog application. This advice completely misses the point. Logtalk objects (which are capable of playing the role of both classes and prototypes) subsume Prolog modules and can do everything Prolog modules do and much more with elegance and aplomb.
1 Here we will only be discussing predicate-based Prolog modules. A few Prolog modules systems are atom-based (e.g. XSB) but comparing them is a topic for another post. ↩