Using the Portray Hook

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

If X is a variable, it is printed using write(X). Otherwise the user-definable procedure user:portray(X) is called. If this succeeds, it is assumed that X has been printed and print/[1,2] exits (succeeds).

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

When print/[1,2] has to print a list, say [X1,X2,…,Xn], it passes the whole list to user:portray/1. As usual, if user:portray/1 succeeds, it is assumed to have printed the entire list, and print/[1,2] does nothing further with this term. Otherwise print/[1,2] writes the list using bracket notation, calling print/[1,2] 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,2] to be called recursively on the two arguments X1 and [X2,…,Xn], giving user:portray/1 a second chance at [X2,…,Xn]. This does not happen; lists are a special case in which print/[1,2] is called separately for each of X1,X2,…Xn.

Send feedback on this subject.