Using the portray hook

print/1 is called from within the system in two places:

  1. to print the bindings of variables after a question has succeeded
  2. to print a goal during debugging

By default, the effect of print/1 is the same as that of write/1, but you can change its effect by providing clauses for the hook predicate portray/1.

If X is a variable, then it is printed using write(X). Otherwise the user-definable procedure portray(X) is called. If this succeeds, then it is assumed that X has been printed and print/1 exits (succeeds). Note that print/1 always calls portray/1 in module user. Therefore, to be visible to print/1, portray/1 must either be defined in or imported into module user.

If the call to portray/1 fails, and if X is a compound term, then write/1 is used to write the principal functor of X and print/1 is called recursively on its arguments. If X is atomic, it is written using write/1.

When print/1 has to print a list, say [X1,X2,...,Xn], it passes the whole list to portray/1. As usual, if portray/1 succeeds, it is assumed to have printed the entire list, and print/1 does nothing further with this term. Otherwise print/1 writes the list using bracket notation, calling print/1 on each element of the list in turn.

Since [X1,X2,...,Xn] is simply a different way of writing .(X1,[X2,...,Xn]), one might expect print/1 to be called recursively on the two arguments X1 and [X2,...,Xn], giving portray/1 a second chance at [X2,...,Xn]. This does not happen; lists are a special case in which print/1 is called separately for each of X1,X2,...Xn.

If you would like lists of character codes printed by print/1 using double-quote notation, you should include library(printchars) (described in lib) as part of your version of portray/1.

Often it is desirable to define clauses for portray/1 in different files. This can be achieved either by declaring it multifile in each of the files, or by using library(addportray).