Notes on PLDoc, PLunit, modules... for anyone interested

I’ve combined various notes I’ve written over the years and put them on the web at
Documenting, testing, and moduling on how to develop software projects using SWI Prolog.

Hopefully other people will find these helpful. Any corrections, constructive criticism etc welcome.

I edited the above since I moved my notes to a different URL

1 Like

Always good if nice stories popup on the internet! A quick read make me propose a few changes:

  • :- use_module(["bestmove.pl", "tictactoe.pl"]).
    I would not propose to push strings for importing modules. Probably even move important, do not include the extension. If you leave that out you need no quotes at all and the system will automatically manage .qlf files: If present and more recent than the .pl file and compatible with the current system, it will load it. If present but otherwise unusable and writable, it will create a new .qlf file and use it.

  • assertion(Move = [does(white, mark(3, 1)), does(black, noop)])
    If a test produces an answer, you better use test(Name, Var == Value), which expresses the test is supposed to succeed and bind Var to Value (you can also use =@= or even =:=). Using the second argument of test to specify the expected result mostly leads to better feedback. I only use assertion/2 if it is useful to test intermediate results.

  • The type hierarchy is flawed in a number of places. I think @dtonhofer provided a diagram for this? Some examples

    • I don’t know about constant
    • There are nowadays also rational numbers
    • blob is above atom. Atom is a subtype of blob.
    • Text can also be lists of codes or chars
    • boolean is a subtype of atom.
    • callable is a disjunctive type of atom and compound.
  • listing(:What)
    Do not forget ?- edit(What). That makes it really easy to get to the source of anything without knowing where it is defined!

2 Likes

Thanks @jan I’ve updated the bestmove.plt example in my online notes.

Something I remain confused about is use_module([bestmove, tictactoe]) will use
(generating updated versions if necessary) bestmove.qlf and tictactoe.qlf only if
they exist? So you have to have run qcompile(:File) at least once to make this work?

The documentation for [ must_be (+Type, @Term)] (must_be/2) has

constant Same as atomic

in its table, so I think that’s where I got it from. I’ll put updating my ASCII artwork of SWI Prolog’s type hierarchy on my todo list, but for now just include a link to this thread.

You merely have to have an empty file called File.qlf; when you load File, the loader will decide that File.qlf is incompatible and will compile File.pl into File.qlf (and also load it). If you exit and restart swipl and load File, you’ll get the new File.qlf (and a much faster load).

1 Like

Ok. I have my doubt we should consider the Type argument of must_be/2 as a proper set of types. It is a rather inconsistent set of “constraints” (?) on arguments that have proven to have some practical usage. The whole notion of a type is a bit unclear in Prolog. Is a character code a type? It is merely a domain restriction on integers. That is a bit different from statically typed languages where a type typically refers to some data structure with a defined layout in memory.

The hard types in SWI-Prolog are integer, rational, float, blob and compound (I think). Blob can dynamically grow sub-types. Atom is predefined. Stream, clause reference, thread reference, mutex reference, etc are all subtypes of blob. These blob types could be considered proper types as the define their own memory layout and operations. They share how the Prolog inference engine deal with them in unification and how garbage collection works on them. For compounds, lists and dicts play a special role.

2 Likes

Note there is also a flag qcompile and an option qcompile(How) to load_files/2 that can be used to instruct the system to automatically maintain .qlf files as in never, auto or large, The latter automatically creates and maintains .qlf files for large source files if the directory that contains the .pl file is writable. That is quite useful for large data files.