I would like to know what are the best practices for sharing Prolog code / libraries with other programmers (and with oneself between multiple projects). I am using SWI-Prolog myself, but are also interested in how other Prologs tackle this.
For comparison, Java has Maven+JARs, Python has EasyInstall+PythonEggs, and there are probably many others for other languages as well. But are there any for Prolog?
SWI-Prolog Packs
In SWI-Prolog there are Packs, supported by module library(prolog_pack)
. The downsides to these are:
- You have to create either an archive file or a Git repository for each pack. Say I want to create 10 packs. Now I need to create 10 Git repositories. I sometimes make edits that impact multiple files, potentially residing in multiple packs/repos, requiring me to commit several Git repositories for a single (multi-file) edit.
- In order to create a pack you have to hand-pick a number of files that 'belong together'. Sometimes I find out that a file X belongs to pack A as well as pack B. Now I need to maintain copies of file X in repositories A and B, or I need to create yet another pack C consisting of only X and import C into A and B.
- Packs are published on a public Web site. Most of my libraries are only interesting for me. A bunch of them are interesting to specific people that I collaborate with, and only a few are 'ready' for wider/public dissemination.
- The pack maintainer has to specify inter-pack dependencies. For intricate hierarchies of libraries that seems like unnecessary work to me. I already use Prolog modules quite stringently and would like to simply use the hierarchy of Prolog module imports as the dependency graph.
Git submodule
Another approach, one that I've used until now, is Git submodules. Dependencies between libraries are achieved by importing one repository into another. This has some of the same downsides as SWI-Prolog packs:
- A Git repository for each library, and thus lots of repositories to maintain.
- The maintainer has to choose the files per repo wisely and has to specify which Git submodule inclusions are needed.
- Updating existing libraries is very difficult. I have found out (the hard way) that most of the people I hand my code to are unable to update a Git repository with many intricately interdependent submodule imports successfully. (I have the utmost respect for the occasional Git guru who uses submodules and always gets it right, but most non-programmers and quite a few programmers I work with find it too difficult.)
My ideal approach
My personal preferences for a perfect Prolog code sharing methodology would be:
- The number of libraries you disseminate and the number of Git repositories you have are independent. Specifically, I can have a sizable repository, parts of which get disseminated in different ways. If somebody likes to (re)use my Prolog module with DCG helper predicates, then I can simply disseminate that single file (plus potential dependencies) to that person.
- You do not have to hand-pick and manually copy individual files, rather you let an algorithm traverse the hierarchy of module imports to extract those files that (apparently) belong together. The files are downloaded when the program is run for the first time. The files may all belong to the same Git repository or to several, the algorithm should not care at all about the mapping between repositories and libraries or between repositories and files.
- The maintainer of the code is able to decide whether a library gets published publicly or to a limited group of people (or to the limited group including only the maintainer).
- The hierarchy of module-imports between files is all you need for dependency-tracking.
The above implies that my ideal library sharing approach is file-based and not package-based. If Prolog module A uses Prolog module B and A is loaded, then B is either loaded from a local file (if it is there) or it is downloaded from a repository. I am not sure how common a file-based approach is in other languages. The aforementioned Maven+JARs and EasyInstall+PythonEggs are both package-based.
I am very interested in what other Prolog programmers use and think about this topic!